Return to threaded-shared-conn.c CVS log | Up to [ELWIX - Embedded LightWeight unIX -] / embedaddon / curl / docs / examples |
1.1 ! misho 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: }