Page 1 of 1

wxSemaphore::TryWait as 'IF' statement condition not working

Posted: Tue Jan 22, 2013 4:04 pm
by softport
Hello, I am trying to test, from a thread, if some code has finished executing in the main thread.
If the main thread is busy, the child thread needs to go on doing other things.

In myForm.cpp, I created a semaphore that signals the status of the code that the child thread is
waiting on:
wxSemaphore mySemaphore(1, 1);

In the child thread I tried using:
if(mySemaphore.TryWait() != wxSEMA_BUSY)

However it always evaluates to false. Having nothing else to try, I changed it to this:
if(mySemaphore.TryWait() == wxSEMA_BUSY)

This always evaluates to false as well. How can they both be false all the time?

From the child thread I can use mySemaphore.Post(), and mySemaphore.Wait() with no problems.
I also tried myThread.WaitTimeout(0) but that didn't work either. I can't get anything to work inside
an if statement except Post():

if(mySemaphore.Post() != wxSEMA_OVERFLOW)

Am I making a mistake somewhere in using TryWait?


Re: wxSemaphore::TryWait as 'IF' statement condition not wor

Posted: Tue Jan 22, 2013 10:34 pm
by Manolo
What kind of code is in myForm.cpp? Sorry for the question, my magic glass ball doesn't work very well.
Hello, I am trying to test, from a thread, if some code has finished executing in the main thread.
If the main thread is busy, the child thread needs to go on doing other things.
Normal coding is that the main thread (let's call it the app) creates and inits a worker thread to do a job. When this thread ends, you may delete it. Is the app who may wait or not for the thread to finish.

If a thread must wait for another thread, use a wxCondition.
If several threads may wait, while others may not, use a wxSemaphore.

My glass doesn't tell me which is the scope of mySemaphore, Or if you have two "mySemaphore" vars, created on different scopes/namespaces with the same name (which will mean different vars, despite of the same name).

Re: wxSemaphore::TryWait as 'IF' statement condition not wor

Posted: Wed Jan 23, 2013 2:34 am
by softport
Thanks Manolo, I will look at wxCondition.

I created a global semaphore in the app (in myForm.cpp), and am using it in both the app and the thread. Apart from calling mySemaphore.Post() in the app, and mySemaphore.Wait() in the thread, there is no other mention of it. I do however have a couple of other global semaphores, and one as a member of a class (left over experiment), so I should check those and clean up the code. Thank you.

The reason the thread is checking on the app:

The thread is reading packets from the USB port and saving them to one of 2 buffers in the app. Say buffer 1.
While the thread is filling buffer 1, the app is getting the information from buffer 2 and displaying it on the screen.
When the app function is done, it issues a mySemaphore.Post()

The thread keeps filling buffer 1, and checking the semaphore to see if the app has finished processing buffer 2.
If the semaphore is clear, the thread tells the app to switch to buffer 1, and the number of new USB packets in buffer 1.

Thread starts filling buffer 2 while the app processes buffer 1.

That's the idea anyway. Since I have not been able to test the semaphore from the thread, the thread is currently having to Wait(), after every single packet, for the app to have processed the previous single packet. I have two buffers of size 50, I can switch buffers, but the max number of packets in each buffer is limited to 1 because I can't get TryWait() to work from the thread.

However, you have jostled my few brain cells, and it just occurred to me to try creating the semaphore in the thread (not the app). Since Post() seems to work from outside the thread where the semaphore was created, it can still be set by the app. Maybe TryWait() will work from inside the thread that created the semaphore. I mean... it has to work somewhere, right? I tried to search for known issues with this command, and didn't find anything.

The file thread.h shows all the functions inside the wxSemaphore, mutex and condition. Maybe a function could be added that returns the semaphore counter as an integer.

Re: wxSemaphore::TryWait as 'IF' statement condition not wor

Posted: Wed Jan 23, 2013 1:20 pm
by softport
Well, have to report no success.

I tried making a semaphore from inside the thread, but I couldn't make it visible to the main app.
I tried using a global mutex, but got the same results as with the semaphore.

Here's a quote from Cross-Platform Gui Programming With WxWidgets:
"If you are in a thread that can do other work if it cannot lock the mutex, you should call wxMutex::TryLock"

When I do that, the program crashes. Debugger message:

"Thread 2 stopped in wxMutex::TryLock() at line 5808667 in with Segmentation fault
Debugger closed."

The same thing happens with wxSemaphore::TryWait

The sun is up, and it looks like the day would be better spent sleeping.
Update, problem solved another way.

Made a global variable "bool bAppBusy" in frm.cpp
The app sets this flag whenever it's busy processing a buffer.

When the thread is created, it is passed a pointer to bAppBusy.
The thread makes a local private copy of the pointer, and can check if the app is busy any time it wants.

All Wait(), TryWait, TryLock, TryNotToCrash() commented out, and the program seems to run much faster.

I'd still like to know why my semaphores and mutexes didn't work, so I'll try and put together some minimal
code that reproduces the problem. For example, the mutex is declared as a pointer, so maybe I was dereferencing
wrong in the thread. The semaphore is not declared as a pointer though.