Re: [gtk-list] Re: gdk_threads_enter is not reentrant



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:wilhelmi@ira.uka.de           |     ä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));
}


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