Hi Richard,
As far as I understand from your pseudo code you are doing the same mistake as I did in my first effort, namely to lock the same mutex twice in the same thread, and to expect that the second invocation will block until another thread releases the mutex. You do this in 3 and in 6. Indeed I, like you, found out that this works under Linux, but Tor pointed out that the documentation states that this is undefined behaviour, and indeed it does not work under Windows. That's why I used the GCond instead.
Regards,
Dov
As far as I understand from your pseudo code you are doing the same mistake as I did in my first effort, namely to lock the same mutex twice in the same thread, and to expect that the second invocation will block until another thread releases the mutex. You do this in 3 and in 6. Indeed I, like you, found out that this works under Linux, but Tor pointed out that the documentation states that this is undefined behaviour, and indeed it does not work under Windows. That's why I used the GCond instead.
Regards,
Dov
2009/7/7 richard boaz <ivor.boaz@xxxxxxxxx>
Hi Dov,
I have solved this in a diferent way that does seem to be a bit easier, and is a little more like your first algorithm. (indeed, your second solution does seem a bit convoluted.)
First, different from your mutex, I'm using a static mutex that is referenced everywhere. And, my program is not one of a GUI and a worker thread, but between the main program and multiple worker threads, though the general idea is the same.
The general algorithm is:i've also attached my code. the program is fairly short, so should be easy to follow. But to make a little more obvious from the algorithm above:
- main thread (M) does program setup
- M then calls routine (TM) directly to set up the worker threads (i.e, TM is NOT a separate thread from M)
- TM immediately locks the static mutex
- TM then creates as many threads (Tn) as there are CPU's available
- TM returns control to M
- M: upon return from TM, immediately calls g_static_mutex_lock(), blocking flow since this has already been locked in step 3.
- Tn: all threads do their work until complete. Once complete, each thread calls a common thread finish routine (TF) that keeps track of when all threads have completed.
- TF: Once all threads are complete, static mutex locked in step 3 is unlocked.
- M: block from step 6 can now continue
the question, of course, is will this work under windows? not sure, my code is only run under linux systems and it works fine there.
- M = main() (file pqlxPNG.c, line 31)
- TM = systemPDF() (file systemPDF.c, line 149)
- Tn = getPdfPng() (file systemPDF.c, line 99; threads created at line 280 in TM routine)
- TF = finishPdfPng() (file systemPDF.c, line 139)
- static mutex = mainMutex (file pqlxPNG.c, line 28; file systemPDF.c, line 74)
- (another static mutex, named myMutex, is used for other reasons, ignore this one)
cheers,
richardOn Tue, Jul 7, 2009 at 9:56 AM, Dov Grobgeld <dov.grobgeld@xxxxxxxxx> wrote:
Thanks a lot for the help.! I have now solved the problem by
introducing a GCond,called C below, into the flow. For posterity, here
is the modified flow, which is actually a general model of a
client-server interaction between a worker thread and the gui thread.
* W locks j->M through g_mutex_lock(j->M) so that G will not send
the condition signal until we are ready for it.
* W fills in j with various info to display.
* W calls g_idle_add(GSourceFunc(cb_update_job), j) to indicate to
G that there is info to display.
* W waits on C through g_cond_wait(j->C, j->M). This will unblock
j->M and allow G to continue.
* G is called in cb_update_job().
* G updates the gui, also possibly updates j based on GUI interaction.
* G does g_mutex_lock(j->M) which causes it to wait until W has
reached g_cond_wait().
* G sends a condition signal through g_cond_signal(j->C)
* G does g_mutex_unlock(j->M). This will allow W to take the lock
in g_cond_wait().
* W wakes up and does a g_mutex_unlock(j->M) as it no longer needs
the lock on the mutex.
* W examines the return info that G filled in into j and contiues
or aborts its operation.
Quite complex I have to admit. Is there a simpler way to solve the
same problem (query/response)?
Regards,
Dov
2009/7/7 Chris Vine <chris@xxxxxxxxxxxxxxxxxxxxx>
>
> On Mon, 6 Jul 2009 17:13:07 +0300
> Dov Grobgeld <dov.grobgeld@xxxxxxxxx> wrote:
>
> > I'm having a problem with GMutex under Windows that don't lock. The
> > behaviour is definitely different from that under Linux.
> >
> > The system is composed of to threads. A gui thread G and a worker
> > thread W. The ping pong between the threads via a mutex j->M should
> > work as follows. j is a job data structure that carries info between
> > the worker thread and the gui thread.
> >
> > 1. W locks j->M through g_mutex_lock(j->M) so that a subsequent
> > lock will block.
> > 2. W fills in j with various info to display.
> > 3. W calls g_idle_add(GSourceFunc(cb_update_job), j) to indicate
> > to G that there is info to display.
> > 4. W blocks on M through a second call to g_mutex_lock(j->M)
> > 5. G is called in cb_update_job() and updates the gui, also
> > possibly updates j, and then does g_mutex_unlock(j->M)
> > 6. W wakes up and does a g_mutex_unlock(j->M) as it no longer
> > needs the lock on the mutex.
> > 7. W examines the return info that G filled in into j and contiues
> > or aborts its operation.
> >
> > The problem on Win32 is that g_mutex_lock in 4 doesn't block and the
> > thread continues, which eventually will cause the system to crash.
> >
> > Is something supposed to be different under Windows, or should I file
> > a bug?
>
> This won't work. Mutexes have ownership once locked. An unlock
> operation on a mutex must be carried out by the same thread that locked
> it.
>
> You could use condition variables to achieve what you want. It would
> also be wise to read up a little more on threading, and in particular
> pthreads (which GThreads mimic).
>
> Chris
>_______________________________________________
gtk-list mailing list
gtk-list@xxxxxxxxx
http://mail.gnome.org/mailman/listinfo/gtk-list
_______________________________________________ gtk-list mailing list gtk-list@xxxxxxxxx http://mail.gnome.org/mailman/listinfo/gtk-list