Annotation of embedaddon/curl/docs/examples/smooth-gtk-thread.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:  * A multi threaded application that uses a progress bar to show
                     24:  * status.  It uses Gtk+ to make a smooth pulse.
                     25:  * </DESC>
                     26:  */
                     27: /*
                     28:  * Written by Jud Bishop after studying the other examples provided with
                     29:  * libcurl.
                     30:  *
                     31:  * To compile (on a single line):
                     32:  * gcc -ggdb `pkg-config --cflags  --libs gtk+-2.0` -lcurl -lssl -lcrypto
                     33:  *   -lgthread-2.0 -dl  smooth-gtk-thread.c -o smooth-gtk-thread
                     34:  */
                     35: 
                     36: #include <stdio.h>
                     37: #include <gtk/gtk.h>
                     38: #include <glib.h>
                     39: #include <unistd.h>
                     40: #include <pthread.h>
                     41: 
                     42: #include <curl/curl.h>
                     43: 
                     44: #define NUMT 4
                     45: 
                     46: pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
                     47: int j = 0;
                     48: gint num_urls = 9; /* Just make sure this is less than urls[]*/
                     49: const char * const urls[]= {
                     50:   "90022",
                     51:   "90023",
                     52:   "90024",
                     53:   "90025",
                     54:   "90026",
                     55:   "90027",
                     56:   "90028",
                     57:   "90029",
                     58:   "90030"
                     59: };
                     60: 
                     61: size_t write_file(void *ptr, size_t size, size_t nmemb, FILE *stream)
                     62: {
                     63:   /* printf("write_file\n"); */
                     64:   return fwrite(ptr, size, nmemb, stream);
                     65: }
                     66: 
                     67: /* https://weather.com/weather/today/l/46214?cc=*&dayf=5&unit=i */
                     68: void *pull_one_url(void *NaN)
                     69: {
                     70:   /* Stop threads from entering unless j is incremented */
                     71:   pthread_mutex_lock(&lock);
                     72:   while(j < num_urls) {
                     73:     CURL *curl;
                     74:     gchar *http;
                     75: 
                     76:     printf("j = %d\n", j);
                     77: 
                     78:     http =
                     79:       g_strdup_printf("xoap.weather.com/weather/local/%s?cc=*&dayf=5&unit=i\n",
                     80:                       urls[j]);
                     81: 
                     82:     printf("http %s", http);
                     83: 
                     84:     curl = curl_easy_init();
                     85:     if(curl) {
                     86: 
                     87:       FILE *outfile = fopen(urls[j], "wb");
                     88: 
                     89:       /* Set the URL and transfer type */
                     90:       curl_easy_setopt(curl, CURLOPT_URL, http);
                     91: 
                     92:       /* Write to the file */
                     93:       curl_easy_setopt(curl, CURLOPT_WRITEDATA, outfile);
                     94:       curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_file);
                     95: 
                     96:       j++;  /* critical line */
                     97:       pthread_mutex_unlock(&lock);
                     98: 
                     99:       curl_easy_perform(curl);
                    100: 
                    101:       fclose(outfile);
                    102:       printf("fclose\n");
                    103: 
                    104:       curl_easy_cleanup(curl);
                    105:     }
                    106:     g_free(http);
                    107: 
                    108:     /* Adds more latency, testing the mutex.*/
                    109:     sleep(1);
                    110: 
                    111:   } /* end while */
                    112:   return NULL;
                    113: }
                    114: 
                    115: 
                    116: gboolean pulse_bar(gpointer data)
                    117: {
                    118:   gdk_threads_enter();
                    119:   gtk_progress_bar_pulse(GTK_PROGRESS_BAR (data));
                    120:   gdk_threads_leave();
                    121: 
                    122:   /* Return true so the function will be called again;
                    123:    * returning false removes this timeout function.
                    124:    */
                    125:   return TRUE;
                    126: }
                    127: 
                    128: void *create_thread(void *progress_bar)
                    129: {
                    130:   pthread_t tid[NUMT];
                    131:   int i;
                    132: 
                    133:   /* Make sure I don't create more threads than urls. */
                    134:   for(i = 0; i < NUMT && i < num_urls ; i++) {
                    135:     int error = pthread_create(&tid[i],
                    136:                                NULL, /* default attributes please */
                    137:                                pull_one_url,
                    138:                                NULL);
                    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, urls[i]);
                    143:   }
                    144: 
                    145:   /* Wait for all threads to terminate. */
                    146:   for(i = 0; i < NUMT && i < num_urls; i++) {
                    147:     pthread_join(tid[i], NULL);
                    148:     fprintf(stderr, "Thread %d terminated\n", i);
                    149:   }
                    150: 
                    151:   /* This stops the pulsing if you have it turned on in the progress bar
                    152:      section */
                    153:   g_source_remove(GPOINTER_TO_INT(g_object_get_data(G_OBJECT(progress_bar),
                    154:                                                     "pulse_id")));
                    155: 
                    156:   /* This destroys the progress bar */
                    157:   gtk_widget_destroy(progress_bar);
                    158: 
                    159:   /* [Un]Comment this out to kill the program rather than pushing close. */
                    160:   /* gtk_main_quit(); */
                    161: 
                    162: 
                    163:   return NULL;
                    164: 
                    165: }
                    166: 
                    167: static gboolean cb_delete(GtkWidget *window, gpointer data)
                    168: {
                    169:   gtk_main_quit();
                    170:   return FALSE;
                    171: }
                    172: 
                    173: int main(int argc, char **argv)
                    174: {
                    175:   GtkWidget *top_window, *outside_frame, *inside_frame, *progress_bar;
                    176: 
                    177:   /* Must initialize libcurl before any threads are started */
                    178:   curl_global_init(CURL_GLOBAL_ALL);
                    179: 
                    180:   /* Init thread */
                    181:   g_thread_init(NULL);
                    182:   gdk_threads_init();
                    183:   gdk_threads_enter();
                    184: 
                    185:   gtk_init(&argc, &argv);
                    186: 
                    187:   /* Base window */
                    188:   top_window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
                    189: 
                    190:   /* Frame */
                    191:   outside_frame = gtk_frame_new(NULL);
                    192:   gtk_frame_set_shadow_type(GTK_FRAME(outside_frame), GTK_SHADOW_OUT);
                    193:   gtk_container_add(GTK_CONTAINER(top_window), outside_frame);
                    194: 
                    195:   /* Frame */
                    196:   inside_frame = gtk_frame_new(NULL);
                    197:   gtk_frame_set_shadow_type(GTK_FRAME(inside_frame), GTK_SHADOW_IN);
                    198:   gtk_container_set_border_width(GTK_CONTAINER(inside_frame), 5);
                    199:   gtk_container_add(GTK_CONTAINER(outside_frame), inside_frame);
                    200: 
                    201:   /* Progress bar */
                    202:   progress_bar = gtk_progress_bar_new();
                    203:   gtk_progress_bar_pulse(GTK_PROGRESS_BAR (progress_bar));
                    204:   /* Make uniform pulsing */
                    205:   gint pulse_ref = g_timeout_add(300, pulse_bar, progress_bar);
                    206:   g_object_set_data(G_OBJECT(progress_bar), "pulse_id",
                    207:                     GINT_TO_POINTER(pulse_ref));
                    208:   gtk_container_add(GTK_CONTAINER(inside_frame), progress_bar);
                    209: 
                    210:   gtk_widget_show_all(top_window);
                    211:   printf("gtk_widget_show_all\n");
                    212: 
                    213:   g_signal_connect(G_OBJECT (top_window), "delete-event",
                    214:                    G_CALLBACK(cb_delete), NULL);
                    215: 
                    216:   if(!g_thread_create(&create_thread, progress_bar, FALSE, NULL) != 0)
                    217:     g_warning("can't create the thread");
                    218: 
                    219:   gtk_main();
                    220:   gdk_threads_leave();
                    221:   printf("gdk_threads_leave\n");
                    222: 
                    223:   return 0;
                    224: }

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