TCondVar broken?

BlitzMax Forums/BlitzMax Programming/TCondVar broken?

BORNtobeNAMELESS(Posted 2010) [#1]
If i understood TCondVar right(Read some stuff about them on google and think i know what they should be doing), shouldn't this Code wait forever, as there is no thread which will ever Signal the condvar?



But instead of blocking forever, it just prints out Juche! and exits?!
Am i doing something wrong with CondVars, or is this a bug in BRL.Threads?

Edit: Seems to happen only on Windows. On Linux and MacOS people say it's waiting.
Edit2: Even locking the same mutex 2 times doesn't stop the program from running. Is there something broken concerning mutexes?


Dreamora(Posted 2010) [#2]
It seems like the code in the threads.c is broken.

In threads_WaitCond, replace:
SignalObjectAndWait( mutex,cond->queue_sem,INFINITE,FALSE );

with:
bb_mutex_unlock( mutex );
WaitForSingleObject( cond->queue_sem,INFINITE );

that cures it at least on Win7 and fixes both issues (1. not waiting at all and once you get waiting fixed -> not releasing the mutex as it enters the wait for signal)

I'm not 100% sure I got the real reason, but to my understanding the problem seems to be that BM pretends to use mutexes but in reality uses EnterCriticalSection macros instead of using Mutex, yet SignalObjectAndWait would require a mutex.


BORNtobeNAMELESS(Posted 2010) [#3]
Works great, thanks.

Here's an other solution i wrote for this, but it only works on Win Vista and higher, not XP and/or 2k:



Behaves exactly like the regular CondVar, except that it works. Should be possible to combine this with the normal CondVar in case loading the funktions failed.


marksibly(Posted 2010) [#4]
Hi,

The problem is indeed due to the new 'fast' Win32 mutexes, but the above solution does not look threadsafe to me - SignalObjectAndWait is atomic; unlock/wait is not.

I still have no real idea what condvars are all about (and regret adding them now!) but will see if I can come with a solution to this that doesn't involve reverting to 'slow' mutexes.

I am also curious to know what people are actually using condvars for - and whether they could achieve the same thing with a semaphore (which also 'counts').


Dreamora(Posted 2010) [#5]
I guess the solution isn't fully "clean" myself, but I just wanted to offer a simple solution that works without replacing the whole critical section code that "fakes mutex on windows" to the correct mutex calls


took me a bit of time and BtbNs help to understand the direct use of condvars, but from what I understand, they are really strong and usefull to "pause threads" and wake them on signal (up to a given point replicable through semaphores, with a bit deeper implementation fully replicable as the condvars near granted use semaphores behind the scenes anyway)


marksibly(Posted 2010) [#6]
Eek,

Ok, not really sure what to do here.

* I could revert to 'old style' mutexes, which fixes all this but are significantly slower and KILLS performance of the GC in threaded mode.

* We could introduce another type of mutex purely for the sake of this issue.

* We could in fact use dreamoras fix above - it is apparently 'safe', just 'unfair', the problem being that a context switch between the unlock and the wait (which is likely if another thread is trying to lock) could end up starving the thread. There are some pretty horrific solutions to this out there, but they're beyond my meagre MT skills.

Again, I'd like to know what people are actually using condvars for in the real world - just saying 'they're really strong' is a little vague, sorry!


marksibly(Posted 2010) [#7]
Hi,

Ok, I've decided to implement my own version of condvars that uses the new fast mutexes. This version may not be quite as 'fair' as the unix version, but I expect to improve it over time as I learn more.

So...has someone got a decent example of condvar usage? Something practical would be nice, but just anything that highlights how they work would be enough.


BORNtobeNAMELESS(Posted 2010) [#8]
If you're looking for a decent explanation what CondVars are and do, IBM got something for you:

http://www.ibm.com/developerworks/linux/library/l-posix3/

I'm currently using CondVars to send events to my threads and wait for them without the need for active polling.
In Windows Vista and higher there are native CondVars in the WinApi, which use CriticalSections, but they are not available on 2k and XP, which is quite bad.

My solution to this is a to make a check if the user is on Vista, and if so, load the CondVar-Functions(They are not available in MinGW, don't know why), and use them and CriticalSections for mutexes.
If the user is on a system where loading the CondVar-Function fails, Mutexes use the old, slow, Windows-Mutex-Functions, and CondVars work like they did before.

I created some kind of fork from BRL.Threads, which implements all this. You can find it in my git:

http://git.btbn.de/btbn.mod.git/blob_plain/HEAD:/threads.mod/threads.bmx