Help on Multi-Threaded applicaiton [modified]
-
Cool good luck! Keep in mind: Locking is bad - eliminate it if possible - only lock for as long as necessary, and there's lots of other threads running in the system to mess with your timing :) Mark
Mark Salsbery Microsoft MVP - Visual C++ :java:
I have a question, I tried to implement the same thing in my application (with some difference, in our application we can not grab frame while processing the current image as we have to update other hardware before grabbing next frame). Here is what I tried to do, I have a camera thread and my loop thread. The loop thread waits for the Camera thread to get a new frame and once the camera gets new frame, it waits for the loop thread until it process and signals it to get next frame. Thats the basic idea. After doing the current image analysis and changing the hardware status based upon current image analysis results, I spend around 6-8ms to update some displays and do some logs, so I thought I can signal the camera meanwhile to get new frame. But I am stuck with deadlocks with signal flags between threads.
Loop thread
do{
if (newframe){
do analysis on the frame
signal = true;//signal the camera to get new frame
update displays and do logs for the current frame
}
}while(looprunning);camera thread
do{
if (signal){
newframe = false;
get new frame - takes 20ms
newframe = true;
signal = false;
}
}while(camrunning);I can see an obvious deadlock, how can I get around this problem :confused: ? -thanks
PKNT
-
I have a question, I tried to implement the same thing in my application (with some difference, in our application we can not grab frame while processing the current image as we have to update other hardware before grabbing next frame). Here is what I tried to do, I have a camera thread and my loop thread. The loop thread waits for the Camera thread to get a new frame and once the camera gets new frame, it waits for the loop thread until it process and signals it to get next frame. Thats the basic idea. After doing the current image analysis and changing the hardware status based upon current image analysis results, I spend around 6-8ms to update some displays and do some logs, so I thought I can signal the camera meanwhile to get new frame. But I am stuck with deadlocks with signal flags between threads.
Loop thread
do{
if (newframe){
do analysis on the frame
signal = true;//signal the camera to get new frame
update displays and do logs for the current frame
}
}while(looprunning);camera thread
do{
if (signal){
newframe = false;
get new frame - takes 20ms
newframe = true;
signal = false;
}
}while(camrunning);I can see an obvious deadlock, how can I get around this problem :confused: ? -thanks
PKNT
Flags? no no no :) There's handy synchronization objects for that, something like:
autoreset events:
newframeevent
signaleventLoop thread
do
{
waitForSingleObject(newframeevent)
do analysis on the frame
SetEvent(signalevent) //signal the camera to get new frame
update displays and do logs for the current frame
}
while(looprunning);camera thread
do
{
waitForSingleObject(signalevent)
get new frame - takes 20ms
SetEvent(newframeevent)
}
while(camrunning);The worst thing I see in the flags implementation is two threads modifying the signal flag. Mark
Mark Salsbery Microsoft MVP - Visual C++ :java:
-
Flags? no no no :) There's handy synchronization objects for that, something like:
autoreset events:
newframeevent
signaleventLoop thread
do
{
waitForSingleObject(newframeevent)
do analysis on the frame
SetEvent(signalevent) //signal the camera to get new frame
update displays and do logs for the current frame
}
while(looprunning);camera thread
do
{
waitForSingleObject(signalevent)
get new frame - takes 20ms
SetEvent(newframeevent)
}
while(camrunning);The worst thing I see in the flags implementation is two threads modifying the signal flag. Mark
Mark Salsbery Microsoft MVP - Visual C++ :java:
Thanks, I feel like a complete dumbo. I always use CEvent::WaitForSingleObject(,) in many threads so that they wont lock the CPU and never thought of using them here. Maybe I need to start thinking slowly ;P
PKNT
-
Thanks, I feel like a complete dumbo. I always use CEvent::WaitForSingleObject(,) in many threads so that they wont lock the CPU and never thought of using them here. Maybe I need to start thinking slowly ;P
PKNT
:)
Kiran Satish wrote:
I always use CEvent::WaitForSingleObject(,) in many threads so that they wont lock the CPU
Yes!. It also throttles your thread loops so they don't sit there spinning while waiting for the flag to be set, eating all your CPU for 1 processor (each). Mark
Mark Salsbery Microsoft MVP - Visual C++ :java:
-
Thanks, I feel like a complete dumbo. I always use CEvent::WaitForSingleObject(,) in many threads so that they wont lock the CPU and never thought of using them here. Maybe I need to start thinking slowly ;P
PKNT
plus...you can add a terminate event if needed so the threads can be shutdown gracefully. Then you'd wait on multiple objects. Mark
Mark Salsbery Microsoft MVP - Visual C++ :java:
-
Flags? no no no :) There's handy synchronization objects for that, something like:
autoreset events:
newframeevent
signaleventLoop thread
do
{
waitForSingleObject(newframeevent)
do analysis on the frame
SetEvent(signalevent) //signal the camera to get new frame
update displays and do logs for the current frame
}
while(looprunning);camera thread
do
{
waitForSingleObject(signalevent)
get new frame - takes 20ms
SetEvent(newframeevent)
}
while(camrunning);The worst thing I see in the flags implementation is two threads modifying the signal flag. Mark
Mark Salsbery Microsoft MVP - Visual C++ :java:
I tried to implement this in simple way to test and rather than waiting for the event to occur, it runs continuously even I define the timeout value to be INIFINITE
getsnap()
{
start camera thread if not running
PulseEvent(getnewframe)
waitForSingleObject(newframeevent, INFINITE)
return;
}camera thread
do
{
waitForSingleObject(getnewframe, INFINITE)
get new frame - takes 20ms
PulseEvent(newframeevent)
}while(camrunning);Here the camera thread continues running even after taking a frame. I am sure 'm missing something here. Sorry for bothering :) . -thanks
PKNT
-
I tried to implement this in simple way to test and rather than waiting for the event to occur, it runs continuously even I define the timeout value to be INIFINITE
getsnap()
{
start camera thread if not running
PulseEvent(getnewframe)
waitForSingleObject(newframeevent, INFINITE)
return;
}camera thread
do
{
waitForSingleObject(getnewframe, INFINITE)
get new frame - takes 20ms
PulseEvent(newframeevent)
}while(camrunning);Here the camera thread continues running even after taking a frame. I am sure 'm missing something here. Sorry for bothering :) . -thanks
PKNT
I would use (and recommend) SetEvent() on auto-reset events and not PulseEvent(): getnewframe = ::CreateEvent(NULL, FALSE, FALSE, NULL); newframeevent = ::CreateEvent(NULL, FALSE, FALSE, NULL); I can't remember why but something about PulseEvent() is flaky/unreliable if I recall correctly (besides the fact that a thread has to be already waiting on it for it to work, which is bad for this case)....I just know I never use it. Compare that to SetEvent() - "The state of an auto-reset event object remains signaled until a single waiting thread is released". That's the behavior you'd want. Mark
Mark Salsbery Microsoft MVP - Visual C++ :java:
-
I would use (and recommend) SetEvent() on auto-reset events and not PulseEvent(): getnewframe = ::CreateEvent(NULL, FALSE, FALSE, NULL); newframeevent = ::CreateEvent(NULL, FALSE, FALSE, NULL); I can't remember why but something about PulseEvent() is flaky/unreliable if I recall correctly (besides the fact that a thread has to be already waiting on it for it to work, which is bad for this case)....I just know I never use it. Compare that to SetEvent() - "The state of an auto-reset event object remains signaled until a single waiting thread is released". That's the behavior you'd want. Mark
Mark Salsbery Microsoft MVP - Visual C++ :java:
I tired to implement using SetEvent, but it still deadlocks, as I dont see any processor activity at all and just a busy mouse icon on the application interface. Here is how I did it - I defined the event handles at the start of the application in your way rather than using CEvent objects like I did before
getnewframe = ::CreateEvent(NULL, FALSE, FALSE, NULL);
newframeevent = ::CreateEvent(NULL, FALSE, FALSE, NULL);when the user clicks snapshot, I call a function (snapshot)
snapshot(exposure)
{
set camera exposure
start snapshotthread if not running
SetEvent(getnewframe)
::WaitForSingleObject(waitfornewframe, INFINITE);
display the frame
}
.
.
.
camthread
{
do
{
::WaitForSingleObject(getnewframe, INFINITE);
take a 20ms snapshot
SetEvent(waitfornewframe);
}while(camrunning)
}I still dont get where I am doing wrong :confused:. I even tried using a while loop in snapshot function and using a 1ms timeout value for WaitForSingleObject and checking for WAIT_OBJECT_0.
PKNT
-
I tired to implement using SetEvent, but it still deadlocks, as I dont see any processor activity at all and just a busy mouse icon on the application interface. Here is how I did it - I defined the event handles at the start of the application in your way rather than using CEvent objects like I did before
getnewframe = ::CreateEvent(NULL, FALSE, FALSE, NULL);
newframeevent = ::CreateEvent(NULL, FALSE, FALSE, NULL);when the user clicks snapshot, I call a function (snapshot)
snapshot(exposure)
{
set camera exposure
start snapshotthread if not running
SetEvent(getnewframe)
::WaitForSingleObject(waitfornewframe, INFINITE);
display the frame
}
.
.
.
camthread
{
do
{
::WaitForSingleObject(getnewframe, INFINITE);
take a 20ms snapshot
SetEvent(waitfornewframe);
}while(camrunning)
}I still dont get where I am doing wrong :confused:. I even tried using a while loop in snapshot function and using a 1ms timeout value for WaitForSingleObject and checking for WAIT_OBJECT_0.
PKNT
I'm not seeing a deadlock situation in the pseudo code... If you run it in the debugger and break, are both threads sitting in the Wait function? If so, why?
Mark Salsbery Microsoft MVP - Visual C++ :java:
-
I'm not seeing a deadlock situation in the pseudo code... If you run it in the debugger and break, are both threads sitting in the Wait function? If so, why?
Mark Salsbery Microsoft MVP - Visual C++ :java:
Here is what happening in debug more
snapshot(exposure)
{
set camera exposure
start snapshotthread if not running
SetEvent(getnewframe)
::WaitForSingleObject(waitfornewframe, INFINITE); -- set breakpoint(1)
display the frame
}
.
.
.
camthread
{
do
{
dummy variable -- set breakpoint(2)
::WaitForSingleObject(getnewframe, INFINITE);
take a 20ms snapshot
SetEvent(waitfornewframe);
}while(camrunning)
}when I hit snapshot button, the program stops at breakpoint(1) and then goes to breakpoint(2) and thats it from there it does nothing while the C++ interface shows as the program is in [run] mode. From the definitions of SetEvent and WaitForSingleObject I too dont see any thing wrong here. Do they need to be in actual two different threads, I dont think thats the case, interesting!
PKNT
-
Here is what happening in debug more
snapshot(exposure)
{
set camera exposure
start snapshotthread if not running
SetEvent(getnewframe)
::WaitForSingleObject(waitfornewframe, INFINITE); -- set breakpoint(1)
display the frame
}
.
.
.
camthread
{
do
{
dummy variable -- set breakpoint(2)
::WaitForSingleObject(getnewframe, INFINITE);
take a 20ms snapshot
SetEvent(waitfornewframe);
}while(camrunning)
}when I hit snapshot button, the program stops at breakpoint(1) and then goes to breakpoint(2) and thats it from there it does nothing while the C++ interface shows as the program is in [run] mode. From the definitions of SetEvent and WaitForSingleObject I too dont see any thing wrong here. Do they need to be in actual two different threads, I dont think thats the case, interesting!
PKNT
hmm the only reason I see that could happen is if "take a 20ms snapshot" never returns so the waitfornewframe event gets set.
Mark Salsbery Microsoft MVP - Visual C++ :java:
-
hmm the only reason I see that could happen is if "take a 20ms snapshot" never returns so the waitfornewframe event gets set.
Mark Salsbery Microsoft MVP - Visual C++ :java:
I even tired that too by commenting it out, but it does the same. will keep tryin different ways and see. Do you think I may need to define those event handles in CMutex objects :~ .
PKNT
-
hmm the only reason I see that could happen is if "take a 20ms snapshot" never returns so the waitfornewframe event gets set.
Mark Salsbery Microsoft MVP - Visual C++ :java:
does it matter how I am defining my thread?? I am using DWORD WINAPI camclass::camthread(LPVOID) form.
PKNT
-
I even tired that too by commenting it out, but it does the same. will keep tryin different ways and see. Do you think I may need to define those event handles in CMutex objects :~ .
PKNT
Kiran Satish wrote:
Do you think I may need to define those event handles in CMutex objects
No that's a different type of synchronization object for mutual exclusion.
Mark Salsbery Microsoft MVP - Visual C++ :java:
-
does it matter how I am defining my thread?? I am using DWORD WINAPI camclass::camthread(LPVOID) form.
PKNT
How are you creating your threads? If you're using MFC and using MFC class objects in your threads you should be using AfxBeginThread(), and the prototype for the thread proc is UINT __cdecl ThreadProc(LPVOID pParam); If you're not using MFC but using CRT functions anywhere in your threads (including new/delete!) then you should be using _beginthread() or _beginthreadex(), and the prototype for the thread proc is unsigned __stdcall ThreadProc(void *lpParameter); For a pure C/C++ thread on Windows which doesn't use MFC or the CRT, you can use ::CreateThread(), and the prototype for the thread proc is DWORD WINAPI ThreadProc(LPVOID lpParameter); For MFC and/or CRT, make sure you're linking to the multithread version of those libraries.
Mark Salsbery Microsoft MVP - Visual C++ :java:
-
hmm the only reason I see that could happen is if "take a 20ms snapshot" never returns so the waitfornewframe event gets set.
Mark Salsbery Microsoft MVP - Visual C++ :java:
I got it running. Unfortunately it doesnt run when I do it the way we discussed earlier, but when I run it in two different threads it works like it should. I am not sure why it did like tht before, but it doesnt work when I have it in between a function and thread.
PKNT
-
I got it running. Unfortunately it doesnt run when I do it the way we discussed earlier, but when I run it in two different threads it works like it should. I am not sure why it did like tht before, but it doesnt work when I have it in between a function and thread.
PKNT
I always thought it was two threads!
Mark Salsbery Microsoft MVP - Visual C++ :java:
-
I always thought it was two threads!
Mark Salsbery Microsoft MVP - Visual C++ :java:
Sorry abt that confusion... maybe I wasnt clear enough.... :), anyway now I know how to use Events in an efficent way... thanks for your help and patience on this...
PKNT
-
Sorry abt that confusion... maybe I wasnt clear enough.... :), anyway now I know how to use Events in an efficent way... thanks for your help and patience on this...
PKNT
Kiran Satish wrote:
maybe I wasnt clear enough
I think I just assumed :) Glad you got it working! Cheers, mark
Mark Salsbery Microsoft MVP - Visual C++ :java:
-
Cool good luck! Keep in mind: Locking is bad - eliminate it if possible - only lock for as long as necessary, and there's lots of other threads running in the system to mess with your timing :) Mark
Mark Salsbery Microsoft MVP - Visual C++ :java:
I am back with another issue in this application :) , saving frames in real-time without dropping and in the same order. I tried using BipBuffer[^]. This is how I implemented, the actual thread keeps running and signals an event to 'SaveImage' thread for every ~20msec where it appends the image data to BipBuffer memory while another thread keeps running all the time saving images from BipBuffer until the BipBuffer memory is NULL. I am allocating 64x(512x512)bytes of memory to BipBuffer. While running like this, the close loop (main thread) starts off at 50Hz and after a while (like 6-7 sec) depending on the size of BipBuffer memory, it slows down to like 39Hz and then goes back to 50Hz slowly. Is there any other way I can save all the images in real-time at 50Hz with out dropping the actual frames coming in from the camera (i.e I have ~17msec to save a particular frame)?? -thanks
PKNT