Re: More questions on threads.



In this example, each thread is allowed to continue undistrubed.. I want
the ability to KILL a thread from a button.

Have you thought about giving your threads a terminal illness?
Make each gtkmain loop have a function that monitors a semaphore
either by creating your own main loop or attaching a function to
the gtk idle function call.  I think the pthread library supports
semaphores last time I played with them.

An example loop might look like this:
while(gtk_main_iteration_do(FALSE) != FALSE)
{
    // semaphore checking code
    if(semaphore_quit())
        break;
}

( I need to build an app which runs and external simulator, monitors it
  in a thread, and has the ability to kill both the monitoring thread and
  external simulation)

I have tried using

 pthread_kill(no_tid, 1);

to kill off a thread, but only managed to destroy the whole app :-(
(I have tried all coded 0->11 btw)..

My heavy modified example of the original gtk-thread.c code (with buttons
to try and kill off the treads is attached.

I look forward to your collective wisdom and guidance..

Best regards

/colin.

  ------------------------------------------------------------------------
#include <gtk/gtk.h>

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <time.h>
#include <gtk/gtk.h>
#include <glib.h>
#include "pthread.h"

#define YES_IT_IS    (1)
#define NO_IT_IS_NOT (0)

pthread_t no_tid, yes_tid;
G_LOCK_DEFINE_STATIC (yes_or_no);
static volatile int yes_or_no = YES_IT_IS;

/**********************/
void
on_kill_thread1_clicked                (GtkButton       *button,
                                        gpointer         user_data)
{
 pthread_kill(no_tid, 1);
}
/**********************/
void
on_kill_thread2_clicked                (GtkButton       *button,
                                        gpointer         user_data)
{
 pthread_kill(yes_tid, 1);
}
/**********************/
typedef struct
{
  GtkWidget *label;
  int what;
} yes_or_no_args;
/**********************/
void destroy(GtkWidget *widget, gpointer data)
{
  gtk_main_quit();
}
/**********************/
void *argument_thread(void *args)
{
  yes_or_no_args *data = (yes_or_no_args *)args;
  gboolean say_something;

  for(;;)
    {
      /* sleep a while */
      sleep(rand() / (RAND_MAX / 3) + 1);

      /* lock the yes_or_no_variable */
      G_LOCK(yes_or_no);

      /* do we have to say something? */
      say_something = (yes_or_no != data->what);

      if(say_something)
        {
          /* set the variable */
          yes_or_no = data->what;
        }

      /* Unlock the yes_or_no variable */
      G_UNLOCK(yes_or_no);

      if(say_something)
        {
          /* get GTK thread lock */
          gdk_threads_enter();

          /* set label text */
          if(data->what == YES_IT_IS)
            gtk_label_set_text(GTK_LABEL(data->label), "O yes, it is!");
          else
            gtk_label_set_text(GTK_LABEL(data->label), "O no, it isn't!");

          /* release GTK thread lock */
           gdk_threads_leave();
        }
    }

  return(NULL);
}

int
main (int argc, char *argv[])
{
  GtkWidget *window;
  GtkWidget *vbox1;
  GtkWidget *label;
  guint kill_thread1_key;
  GtkWidget *kill_thread1;
  guint kill_thread2_key;
  GtkWidget *kill_thread2;
  GtkAccelGroup *accel_group;

  yes_or_no_args yes_args, no_args;

  gtk_set_locale ();

  /* init threads */
  g_thread_init(NULL);

  gtk_init (&argc, &argv);

  /***********************************/
  /* Start to build the main windows */
  accel_group = gtk_accel_group_new ();

  window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
  gtk_object_set_data (GTK_OBJECT (window), "window", window);
  gtk_window_set_title (GTK_WINDOW (window), "window");

  vbox1 = gtk_vbox_new (FALSE, 0);
  gtk_widget_ref (vbox1);
  gtk_object_set_data_full (GTK_OBJECT (window), "vbox1", vbox1,
                            (GtkDestroyNotify) gtk_widget_unref);
  gtk_widget_show (vbox1);
  gtk_container_add (GTK_CONTAINER (window), vbox1);

  label = gtk_label_new ("Nothing yet set...");
  gtk_widget_ref (label);
  gtk_object_set_data_full (GTK_OBJECT (window), "label", label,
                            (GtkDestroyNotify) gtk_widget_unref);
  gtk_widget_show (label);
  gtk_box_pack_start (GTK_BOX (vbox1), label, FALSE, FALSE, 0);

  kill_thread1 = gtk_button_new_with_label ("");
  kill_thread1_key = gtk_label_parse_uline (GTK_LABEL (GTK_BIN (kill_thread1)->child),
                                   "kill_thread1");
  gtk_widget_add_accelerator (kill_thread1, "clicked", accel_group,
                              kill_thread1_key, GDK_MOD1_MASK, 0);
  gtk_widget_ref (kill_thread1);
  gtk_object_set_data_full (GTK_OBJECT (window), "kill_thread1", kill_thread1,
                            (GtkDestroyNotify) gtk_widget_unref);
  gtk_widget_show (kill_thread1);
  gtk_box_pack_start (GTK_BOX (vbox1), kill_thread1, FALSE, FALSE, 0);

  kill_thread2 = gtk_button_new_with_label ("");
  kill_thread2_key = gtk_label_parse_uline (GTK_LABEL (GTK_BIN (kill_thread2)->child),
                                   "kill_thread2");
  gtk_widget_add_accelerator (kill_thread2, "clicked", accel_group,
                              kill_thread2_key, GDK_MOD1_MASK, 0);
  gtk_widget_ref (kill_thread2);
  gtk_object_set_data_full (GTK_OBJECT (window), "kill_thread2", kill_thread2,
                            (GtkDestroyNotify) gtk_widget_unref);
  gtk_widget_show (kill_thread2);
  gtk_box_pack_start (GTK_BOX (vbox1), kill_thread2, FALSE, FALSE, 0);

  gtk_signal_connect (GTK_OBJECT (kill_thread1), "clicked",
                      GTK_SIGNAL_FUNC (on_kill_thread1_clicked),
                      NULL);
  gtk_signal_connect (GTK_OBJECT (kill_thread2), "clicked",
                      GTK_SIGNAL_FUNC (on_kill_thread2_clicked),
                      NULL);

  gtk_signal_connect(GTK_OBJECT (window), "destroy",
                     GTK_SIGNAL_FUNC(destroy),
                     NULL);

  gtk_window_add_accel_group (GTK_WINDOW (window), accel_group);

  /***********************************/

  /* create the threads */
  yes_args.label = label;
  yes_args.what = YES_IT_IS;
  pthread_create(&yes_tid, NULL, argument_thread, &yes_args);

  no_args.label = label;
  no_args.what = NO_IT_IS_NOT;
  pthread_create(&no_tid, NULL, argument_thread, &no_args);

  gtk_widget_show (window);

  gdk_threads_enter();
  gtk_main();
  gdk_threads_leave();
  return 0;
}





[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]