Hi Noel,

> Sometimes you really do need to explicitly release a mutex no matter
> what lock depth you're at.  To do so requires you know exactly how
> many time gdk_threads_lock has been called.  Please at least put in a
> gdk_threads_depth counter so users can do their own lock release.
> 
> Multithreaded programs really need to be able to do this, and it's
> trivial to do, no matter what threads implementation you use.

No, it isn't, when I'm using the native recursive mutex implementation, as
found in Unix98 and also linuxthreads. This native implementation is faster
than the self-implemented one. So I don't think, we'll support that. Appended
is a small test-program to demonstrate the time difference:

Here are the values on my Linux machine.

Homemade: 4.086516 seconds.
Native:   3.230480 seconds.

Bye,
Sebastian
-- 
Sebastian Wilhelmi                   |            h�r ovanf�r alla molnen
mailto:[EMAIL PROTECTED]           |     �r himmlen s� f�runderligt bl�
http://goethe.ira.uka.de/~wilhelmi   |
/* compile with
 *   gcc -o test test.c `glib-config --cflags --libs gthread` -D_GNU_SOURCE
 */

#include <pthread.h>
#include <glib.h>

pthread_mutex_t mutex;

struct my_mutex_t
{
  pthread_mutex_t mutex;
  pthread_t thread;
  gint counter;
  gboolean recursive;
} my_mutex = {PTHREAD_MUTEX_INITIALIZER, 0, 0, 1};

void my_mutex_lock (struct my_mutex_t* mutex)
{
  if (mutex->recursive)
    {
      pthread_t self = pthread_self ();
      if (pthread_equal (self, mutex->thread))
        {
          mutex->counter++;
          return;
        }
      pthread_mutex_lock (&mutex->mutex);
      mutex->thread = self;
      mutex->counter = 0;
    }
  else
    pthread_mutex_lock (&mutex->mutex);
}

void
my_mutex_unlock (struct my_mutex_t* mutex)
{
  if (mutex->recursive)
    {
      if (mutex->counter > 0)
        {
          mutex->counter--;
          return;
        }
      mutex->thread = 0;
    }
  pthread_mutex_unlock (&mutex->mutex);
}

main()
{
  int i;
  GTimer* timer = g_timer_new();  
  pthread_mutexattr_t attr;
  
  pthread_mutexattr_init (&attr);
  pthread_mutexattr_settype (&attr, PTHREAD_MUTEX_RECURSIVE);
  pthread_mutex_init (&mutex, &attr);

  g_timer_start (timer);
  for(i=0; i<1000000; i++)
    {
      my_mutex_lock (&my_mutex);
      my_mutex_lock (&my_mutex);
      my_mutex_lock (&my_mutex);
      my_mutex_lock (&my_mutex);
      my_mutex_unlock (&my_mutex);
      my_mutex_unlock (&my_mutex);
      my_mutex_unlock (&my_mutex);
      my_mutex_unlock (&my_mutex);      
    }
  g_print ("Homemade: %f seconds.\n",  g_timer_elapsed (timer, NULL));
  g_timer_start (timer);
  for(i=0; i<1000000; i++)
    {
      pthread_mutex_lock (&mutex);
      pthread_mutex_lock (&mutex);
      pthread_mutex_lock (&mutex);
      pthread_mutex_lock (&mutex);
      pthread_mutex_unlock (&mutex);
      pthread_mutex_unlock (&mutex);
      pthread_mutex_unlock (&mutex);
      pthread_mutex_unlock (&mutex);      
    }
  g_print ("Native:   %f seconds.\n",  g_timer_elapsed (timer, NULL));
}

Reply via email to