["M.Stekelenburg" <root cal052304 student utwente nl>] Re: thread safe gtk?
- From: Owen Taylor <otaylor gtk org>
- To: gtk-list redhat com
- Subject: ["M.Stekelenburg" <root@cal052304.student.utwente.nl>] Re: thread safe gtk?
- Date: 11 May 1998 18:24:45 -0400
[ Except for a detail or two, and for style, this is pretty much
line-for-line identical to my gtkthreads-0.2. The most significant
difference is that the condition variable is signaled at the
end of gtk_thread_leave() instead of gtk_thread_enter(), which
probably works better for the more typical light contention
on the GTK lock. ]
- From: "M.Stekelenburg" <root cal052304 student utwente nl>
- To: Owen Taylor <otaylor gtk org>
- cc: gtk-list redhat com, Rob Browning <rlb cs utexas edu>, M Stekelenburg student utwente nl
- Subject: Re: thread safe gtk?
- Date: Mon, 11 May 1998 23:37:20 +0200 (MET DST)
(I think this will not get to the gtk-list because it is someone buffers
the list for me)
I've some code please try it, it might be the simple solution ;)
It is a replacement for Owens code except it is missing the
gtk_threads_enter_main and gtk_threads_leave_main.
Max
On 11 May 1998, Owen Taylor wrote:
>
> 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.
>
your right the simple solution is reading the word at a different place
see the attachment. It now removes it request if it is honoured.
> 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 (>k_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 (>k_lock_cond, >k_lock_mutex);
> gtk_lock_nwaiting--;
> }
> gtk_lock_state = GTK_LOCKED;
> pthread_mutex_unlock (>k_lock_mutex);
> }
>
> void
> gtk_threads_leave (void)
> {
> pthread_mutex_lock (>k_lock_mutex);
> gtk_lock_state = GTK_UNLOCKED;
> pthread_cond_signal (>k_lock_cond);
> pthread_mutex_unlock (>k_lock_mutex);
> }
>
> As I said, it seems like there should be a simpler solution.
>
> Regards,
> Owen
>
#include <pthread.h>
#include <gtk/gtk.h>
#include <unistd.h>
/*#define debug(x) printf(x);printf("\n");fflush(stdout); */
#define debug(x)
pthread_cond_t Xcond = PTHREAD_COND_INITIALIZER;
pthread_mutex_t Xmutex= PTHREAD_MUTEX_INITIALIZER;
int Xpipe[2];
void gtk_threads_init(void) {
pipe(Xpipe);
pthread_mutex_lock(&Xmutex);
}
/*this routine is called when something has written to the Xpipe*/
static void threadcall(void *a,int b,GdkInputCondition c) {
debug("call");
pthread_cond_wait(&Xcond,&Xmutex);
debug("call 2");
}
gtk_threads_main(){
gdk_input_add(Xpipe[0],GDK_INPUT_READ,threadcall,0);
gtk_main();
}
/*
gtk_calls not made by the main thread should be wrapped between
gtk_thread_enter and gtk_thread_leave
*/
void gtk_threads_enter(){
char c;
debug("enter");
write(Xpipe[1],"A",1);
debug("enter 2");
pthread_mutex_lock(&Xmutex);
debug("enter 3");
read(Xpipe[0],&c,1);
debug("enter 4");
}
void gtk_threads_leave(){
debug("leave");
pthread_cond_signal(&Xcond);
debug("leave 2");
pthread_mutex_unlock(&Xmutex);
debug("leave 3");
}
gtk_thread_exit(){
pthread_cond_destroy(&Xcond);
pthread_mutex_destroy(&Xmutex);
close(Xpipe[0]);
close(Xpipe[1]);
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]