#include <stdio.h>
#include <gtk/gtk.h>
#include "gtkthreads.h"
#include <pthread.h>

static int nthreads = 0;
static pthread_mutex_t nthreads_mutex = PTHREAD_MUTEX_INITIALIZER;

void
close_cb (GtkWidget *w, gint *flag)
{
  *flag = 1;
}

gint
delete_cb (GtkWidget *w, GdkEvent *event, gint *flag)
{
  *flag = 1;
  return TRUE;
}

void *
counter (void *data)
{
  gchar *name = data;
  gint flag = 0;
  gint counter = 0;
  gchar buffer[32];
  
  GtkWidget *window;
  GtkWidget *vbox;
  GtkWidget *label;
  GtkWidget *button;

  gtk_threads_enter();

  window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
  gtk_window_set_title (GTK_WINDOW (window), name);
  gtk_widget_set_usize (window, 100, 50);

  vbox = gtk_vbox_new (FALSE, 0);

  gtk_signal_connect (GTK_OBJECT (window), "delete_event",
		      GTK_SIGNAL_FUNC (delete_cb), &flag);

  gtk_container_add (GTK_CONTAINER (window), vbox);

  label = gtk_label_new ("0");
  gtk_box_pack_start (GTK_BOX (vbox), label, TRUE, FALSE, 0);

  button = gtk_button_new_with_label ("Close");
  gtk_signal_connect (GTK_OBJECT (button), "clicked",
		      GTK_SIGNAL_FUNC (close_cb), &flag);
  gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);

  gtk_widget_show_all (window);

  /* Since flag is only checked or set inside the GTK lock,
   * we don't have to worry about locking it explicitly
   */
  while (!flag)
    {
      sprintf(buffer, "%d", counter);
      gtk_label_set (GTK_LABEL (label), buffer);
      gtk_threads_leave();
      counter++;
      /* Give someone else a chance to get the lock next time.
       * Only necessary because we don't do anything else while
       * releasing the lock.
       */
      sleep(0);
      
      gtk_threads_enter();
    }

  gtk_widget_destroy (window);

  pthread_mutex_lock (&nthreads_mutex);
  nthreads--;
  if (nthreads == 0)
    gtk_main_quit();
  pthread_mutex_unlock (&nthreads_mutex);

  gtk_threads_leave();

  return NULL;
}

int 
main (int argc, char **argv)
{
  int i;
  
  gtk_init (&argc, &argv);
  gtk_threads_init();

  pthread_mutex_lock (&nthreads_mutex);

  for (i=0; i<5; i++)
    {
      char buffer[10];
      pthread_t thread;
      
      sprintf(buffer, "Thread %i", i);
      if (pthread_create (&thread, NULL, counter, buffer))
	{
	  fprintf(stderr, "Couldn't create thread\n");
	  exit(1);
	}
      nthreads++;
    }

  pthread_mutex_unlock (&nthreads_mutex);

  gtk_threads_main();

  fprintf(stderr, "Done\n");

  return 0;
}
