Annotation of embedaddon/curl/docs/examples/threaded-shared-conn.c, revision 1.1.1.1
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: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>