Re: thread safe gtk?




Rob Browning <rlb@cs.utexas.edu> writes:

> I thought I'd forward this too since it's relevant to anyone following
> this thread.  It's an improved way to handle the X pipe from Max.
> 
> ------- Start of forwarded message -------
> Date: 	Sun, 10 May 1998 01:07:41 +0200 (MET DST)
> From: "M.Stekelenburg" <root@cal052304.student.utwente.nl>
> Reply-To: M.Stekelenburg@student.utwente.nl
> To: Rob Browning <rlb@cs.utexas.edu>
> Subject: Re: [gtk-list] Re: thread safe gtk?
> Message-ID: <Pine.LNX.3.95q.980510010212.1128B-100000@noviomagus.student.utwente.nl>
> MIME-Version: 1.0
> Content-Type: TEXT/PLAIN; charset=US-ASCII
> 
> ok a better version of my code:
> #define XOPEN write(Xpipe[1],"A",1);lock(xmutex);
> #define XCLOSE signal(xthreadcond);unlock(xmutex);
> 
> the pipes etc remain the same but this also changes;
> 
> threadcall(){
>   read(Xpipe[0],&c,1);
>   wait(xthreadcond);
> }
> 
> 
> This use of threadconditions should make sure that control is transfered
> from the gtk_main thread to the requesting and back.
> 
> But this construction is NOT tested.

I think if there are multiple threads trying to get the
lock, a problem can happen:

- Subsidiary thread A tries to get the lock , so it writes  
  to the pipe, then blocks on the lock.

- Subsidiary thread B tries to get the lock, so it writes
  to the pipe, then blocks on the lock.

- Main thread M reads one byte from the pipe, then releases
  the lock. and waits on the condition variable.

- thread A gets the lock, runs, signals the condition variable,
  then release the lock.

- thread B gets the lock, runs, signals the condition variable,
  then releases the lock.

- Main thread M gets the lock, goes back to the main loop,
  sees there still is one byte in the pipe, releases the
  lock and waits on the condition variable. But neither
  A nor B wants the lock now, so the main loop hangs.

There seems like there should be a simple solution to this,
but I really couldn't figure one out. So what I did
in "gtkthreads" was more complicated:

I kept a three-way state variable (unlocked, mainloop, locked),
then as soon as a subsidiary thread wrote to the pipe,
it changed the state from mainloop to locked so that future
threads waiting on the lock would not try to do the same.

The state variable then has to be guarded by a mutex itself,
so the main lock is no longer just a mutex, but is more 
like a condpair. 

void
gtk_threads_enter (void)
{
  pthread_mutex_lock (&gtk_lock_mutex);

  while (gtk_lock_state != GTK_UNLOCKED)
    {
      gtk_lock_nwaiting++;
      if (gtk_lock_state == GTK_MAINLOOP)
	{
	  gtk_lock_state = GTK_LOCKED;
	  write(gtk_lock_pipe[1], "A", 1);
	}
      pthread_cond_wait (&gtk_lock_cond, &gtk_lock_mutex);
      gtk_lock_nwaiting--;
    }
  gtk_lock_state = GTK_LOCKED;
  pthread_mutex_unlock (&gtk_lock_mutex);
}

void
gtk_threads_leave (void)
{
  pthread_mutex_lock (&gtk_lock_mutex);
  gtk_lock_state = GTK_UNLOCKED;
  pthread_cond_signal (&gtk_lock_cond);
  pthread_mutex_unlock (&gtk_lock_mutex);
}

As I said, it seems like there should be a simpler solution.

Regards,
                                        Owen



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