Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>The following code does what I asked. It uses pthreads. I don't know if it's the most elegant but it seems to work. The trick was using two flags: one for the idle state and one for a cancel request, which avoids needing to cancel the thread using the "pthread_cancel" function, which I find to be unusual in real code. </p> <pre><code>#include &lt;gtk/gtk.h&gt; #include &lt;pthread.h&gt; #include &lt;errno.h&gt; #include &lt;stdlib.h&gt; #define UNUSED(x) (void)(x) #define handle_error_en(en, msg) do { errno = en; perror(msg); exit(EXIT_FAILURE); } while (0) typedef struct _Data { GtkWidget *window1, *button1; } Data; static Data *data; static pthread_mutex_t calcmutex = PTHREAD_MUTEX_INITIALIZER; static pthread_t calcthread=0; static gboolean idle=TRUE,cancel_request=FALSE; void *calcfunc(void *arg) { int i,s; UNUSED(arg); g_print("\tstarting thread\n"); s = pthread_setcancelstate(PTHREAD_CANCEL_ASYNCHRONOUS, NULL); if (s != 0) { handle_error_en(s, "pthread_setcancelstate"); } gdk_threads_enter(); gtk_button_set_label(GTK_BUTTON(data-&gt;button1),"Stop"); gdk_threads_leave(); g_print("\tstarting work...\n"); for (i=0; i&lt;100000000 ;++i) { /* check for cancelation */ pthread_mutex_lock(&amp;calcmutex); if ( cancel_request ) { g_print("\t[cancel request noted].\n"); pthread_mutex_unlock(&amp;calcmutex); break; } pthread_mutex_unlock(&amp;calcmutex); /* do "calculation" */ i=i*1*-1*1*-1; } g_print("\tdone work.\n"); gdk_threads_enter(); gtk_button_set_label(GTK_BUTTON(data-&gt;button1),"Start"); gdk_threads_leave(); pthread_mutex_lock(&amp;calcmutex); cancel_request=FALSE; idle=TRUE; pthread_mutex_unlock(&amp;calcmutex); g_print("\tdone thread.\n"); pthread_exit(NULL); } void on_button1_clicked(GtkWidget *widget, gpointer *ldata) { int s; UNUSED(widget); UNUSED(ldata); g_print("entered on_button1_clicked\n"); pthread_mutex_lock(&amp;calcmutex); if ( idle ) { g_print("idle, starting thread\n"); s = pthread_create(&amp;calcthread, NULL, calcfunc, NULL); if (s != 0) { handle_error_en(s, "pthread_create"); } idle=FALSE; } else { g_print("not idle and not first time, making canceling request.\n"); cancel_request=TRUE; } pthread_mutex_unlock(&amp;calcmutex); g_print("finished on_button1_clicked\n"); } /* just defines our setup */ int main (int argc, char *argv[]) { g_thread_init(NULL); gdk_threads_init(); gdk_threads_enter(); gtk_init(&amp;argc, &amp;argv); data=g_slice_new0(Data); printf("initial idle is %d\n",idle); /* add widgets and objects to our structure */ data-&gt;window1=gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_window_set_default_size(GTK_WINDOW(data-&gt;window1),250,250); data-&gt;button1=gtk_button_new_with_label("Start"); gtk_container_add(GTK_CONTAINER(data-&gt;window1),GTK_WIDGET(data-&gt;button1)); gtk_signal_connect(GTK_OBJECT(data-&gt;window1), "delete-event", gtk_main_quit, NULL); gtk_signal_connect(GTK_OBJECT(data-&gt;button1), "clicked", G_CALLBACK(on_button1_clicked), NULL); gtk_widget_show_all(GTK_WIDGET(data-&gt;window1)); gtk_main(); /* free the memory and stuff */ g_slice_free(Data, data); pthread_mutex_destroy(&amp;calcmutex); gdk_threads_leave(); return 0; } </code></pre> <p>This compiles warningless with</p> <pre><code>gcc -Wall -Wextra -Wconversion -pedantic `pkg-config --cflags --libs gtk+-2.0` start_stop.c -o start_stop </code></pre>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload