File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / curl / docs / examples / threaded-shared-conn.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Wed Jun 3 10:01:15 2020 UTC (4 years, 10 months ago) by misho
Branches: curl, MAIN
CVS tags: v7_70_0p4, HEAD
curl

    1: /***************************************************************************
    2:  *                                  _   _ ____  _
    3:  *  Project                     ___| | | |  _ \| |
    4:  *                             / __| | | | |_) | |
    5:  *                            | (__| |_| |  _ <| |___
    6:  *                             \___|\___/|_| \_\_____|
    7:  *
    8:  * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
    9:  *
   10:  * This software is licensed as described in the file COPYING, which
   11:  * you should have received as part of this distribution. The terms
   12:  * are also available at https://curl.haxx.se/docs/copyright.html.
   13:  *
   14:  * You may opt to use, copy, modify, merge, publish, distribute and/or sell
   15:  * copies of the Software, and permit persons to whom the Software is
   16:  * furnished to do so, under the terms of the COPYING file.
   17:  *
   18:  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
   19:  * KIND, either express or implied.
   20:  *
   21:  ***************************************************************************/
   22: /* <DESC>
   23:  * Multi-threaded transfers sharing a single connection pool
   24:  * </DESC>
   25:  *
   26:  * This example fires up NUM_THREADS threads and in each single thread, it
   27:  * downloads the same fixed URL a URL_ITERATIONS number of times. The received
   28:  * data is just thrown away. It sets up a single shared object that holds the
   29:  * connection cache and all easy handles in all threads share that same cache.
   30:  *
   31:  * This example uses pthreads for threads and mutexes, but should be easy to
   32:  * modify to use different thread/mutex system should you want to.
   33:  *
   34:  */
   35: 
   36: #include <stdio.h>
   37: #include <pthread.h>
   38: #include <curl/curl.h>
   39: 
   40: /*
   41:   URL to fetch. If you select HTTPS, you need to use a TLS backend with mutex
   42:   locks taken care of (OpenSSL 1.1.x, NSS, etc) or add SSL mutex callbacks!
   43: */
   44: #define URL "http://localhost/4KB"
   45: 
   46: /* number of threads to fire up in parallel */
   47: #define NUM_THREADS 67
   48: 
   49: /* how many times each URL is transferred per thread */
   50: #define URL_ITERATIONS 11235
   51: 
   52: static pthread_mutex_t connlock;
   53: 
   54: static size_t write_db(void *ptr, size_t size, size_t nmemb, void *data)
   55: {
   56:   /* not interested in the downloaded bytes, return the size */
   57:   (void)ptr;  /* unused */
   58:   (void)data; /* unused */
   59:   return (size_t)(size * nmemb);
   60: }
   61: 
   62: static void lock_cb(CURL *handle, curl_lock_data data,
   63:                     curl_lock_access access, void *userptr)
   64: {
   65:   (void)access; /* unused */
   66:   (void)userptr; /* unused */
   67:   (void)handle; /* unused */
   68:   (void)data; /* unused */
   69:   pthread_mutex_lock(&connlock);
   70: }
   71: 
   72: static void unlock_cb(CURL *handle, curl_lock_data data,
   73:                       void *userptr)
   74: {
   75:   (void)userptr; /* unused */
   76:   (void)handle;  /* unused */
   77:   (void)data;    /* unused */
   78:   pthread_mutex_unlock(&connlock);
   79: }
   80: 
   81: static void init_locks(void)
   82: {
   83:   pthread_mutex_init(&connlock, NULL);
   84: }
   85: 
   86: static void kill_locks(void)
   87: {
   88:   pthread_mutex_destroy(&connlock);
   89: }
   90: 
   91: struct initurl {
   92:   const char *url;
   93:   CURLSH *share;
   94:   int threadno;
   95: };
   96: 
   97: static void *run_thread(void *ptr)
   98: {
   99:   struct initurl *u = (struct initurl *)ptr;
  100:   int i;
  101: 
  102:   for(i = 0; i < URL_ITERATIONS; i++) {
  103:     CURL *curl = curl_easy_init();
  104:     curl_easy_setopt(curl, CURLOPT_URL, u->url);
  105:     curl_easy_setopt(curl, CURLOPT_VERBOSE, 0L);
  106:     curl_easy_setopt(curl, CURLOPT_SHARE, u->share);
  107:     curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_db);
  108:     curl_easy_perform(curl); /* ignores error */
  109:     curl_easy_cleanup(curl);
  110:     fprintf(stderr, "Thread %d transfer %d\n", u->threadno, i);
  111:   }
  112: 
  113:   return NULL;
  114: }
  115: 
  116: int main(void)
  117: {
  118:   pthread_t tid[NUM_THREADS];
  119:   int i;
  120:   CURLSH *share;
  121:   struct initurl url[NUM_THREADS];
  122: 
  123:   /* Must initialize libcurl before any threads are started */
  124:   curl_global_init(CURL_GLOBAL_ALL);
  125: 
  126:   share = curl_share_init();
  127:   curl_share_setopt(share, CURLSHOPT_LOCKFUNC, lock_cb);
  128:   curl_share_setopt(share, CURLSHOPT_UNLOCKFUNC, unlock_cb);
  129:   curl_share_setopt(share, CURLSHOPT_SHARE, CURL_LOCK_DATA_CONNECT);
  130: 
  131:   init_locks();
  132: 
  133:   for(i = 0; i< NUM_THREADS; i++) {
  134:     int error;
  135:     url[i].url = URL;
  136:     url[i].share = share;
  137:     url[i].threadno = i;
  138:     error = pthread_create(&tid[i], NULL, run_thread, &url[i]);
  139:     if(0 != error)
  140:       fprintf(stderr, "Couldn't run thread number %d, errno %d\n", i, error);
  141:     else
  142:       fprintf(stderr, "Thread %d, gets %s\n", i, URL);
  143:   }
  144: 
  145:   /* now wait for all threads to terminate */
  146:   for(i = 0; i< NUM_THREADS; i++) {
  147:     pthread_join(tid[i], NULL);
  148:     fprintf(stderr, "Thread %d terminated\n", i);
  149:   }
  150: 
  151:   kill_locks();
  152: 
  153:   curl_share_cleanup(share);
  154:   curl_global_cleanup();
  155:   return 0;
  156: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>