Link to home
Start Free TrialLog in
Avatar of manx
manx

asked on

Thread Syncronisation


Currently I have 3 threads running. A main application thread and 2 worker threads handling communications between the 2 serial ports.

When the following code is runn problems arise :

((CKRCApp*)AfxGetApp())->GetActivebot()->MoveRight(15);
((CKRCApp*)AfxGetApp())->CapImage.AnalyseImage();

The first line in the code direct a message to be sent out through one of the serial ports via the appropriate worker thread. The message updates the position of a robot.

The second line performs some analysis by the main application thread based on video image recieved from the updated robot position.

The problem is that the first command is executing half way by the worker thread when its time slice ends and the main thread continues the 2nd analysis command. Since the analysis is to be based upon the updated position, it becomes invalid.

This is especially so when the 2 commands are placed in a for loop. Multiple analysis are done on invalid positions.  

Thus is there some way to force the worker thread to execute before running the analysis command?

The main thread cannot be suspended indefinitely as it is responsible for refreshing and updating full motion video to the screen.

thanks and regards

ManX
Avatar of akalmani
akalmani

HI !!
   Hope this helps u out..
  Try to increase the priority of the thread which u want to execute more using setpriority() or another option is
CEvent object a synchronization object that allows one thread to notify another that an event has occurred.
 See the topic of CEvent on msdn for synchronization of threads.
What you're asking is rather simple to achieve.  The first thread that is running, is in a non-signaled state while it is executing.  What you need is a way to inform the second thread that the first thread is finished executing, so that the second thread can then start.

The way you do that is to insert the WaitForSingleObject() function in front of the second thread.

What that will do, is to prevent the second thread from taking off and start running before the first thread is through.  When the first is finished working, the operating system changes its state into that of a signaled state.  This signaled state is then communicated to the second thread which then takes off and start doing its work.  Without this signaled state being received by the second thread, it will NOT start executing.  It will simply sit there and do nothing.  (Now, let me explain what I've just stated, because it depends on what you code as the second parameter for the WaitForSingleObject() API).

The first parameter of WaitForSingleObject uses the handle of the thread that is executing.  The second parameter uses one of three values.

1)  0 (zero) allows you to test the state of the thread and returns immediately.
2)  A millisecond value indicating the time you are willing to wait on the thread.
3)  INFINITE:  this means NO TIMEOUT.  The executing thread will run its full course and finishes whenever it finishes.

If WaitForSingleObject succeeds, it will return one of three values:

1)  WAIT_OBJECT_0 means the object you're waiting for, is now signaled.
2)  WAIT_TIMEOUT means the time you coded as the second parameter has elapsed and the thread is still executing.
3)  WAIT_ABANDONED means the thread exits but did not release a resource (e.g. mutex) before becoming signaled.

In the rare event that WaitForSingleObject did NOT succeed, it returns WAIT_FAILED.


If you have any further questions, don't hesitate.
ASKER CERTIFIED SOLUTION
Avatar of PIG
PIG

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Using CMutex still does NOT get you away from waiting until the first thread becomes signaled.  CMutex simply tells the operating system that you have two (or more) separate processings (threads) that cannot be run at the same time.  The thread that is currently running owns the Mutex (if it had acquired it prior to running) and has to release it in order for another thread to use (own) it.  When no thread owns the Mutex, that is when it becomes signaled.  To acquire ownership of a Mutex, you have to use WaitForSingleObject (or the other "Wait" function), the same function you need to simply inform the second thread that it can start processing.  Using a mutex therefore, will NOT get you away from using WaitForSingleObject, only this time you'll be using the function to acquire a mutex instead of simply telling the second thread it can start processing.

The bottom line:  You DO NOT need to create a Mutex in order to schedule execution of a thread before another.  WaitForSingleObject will prevent the other thread from executing UNTIL the first thread has signaled to the other thread that it is finished.  Period!!

Using a Mutex, a Critical Section, a Semaphore or any of the other means to obtain thread synchronization, in this instance is nothing more than an overkill, and it requires MORE work and MORE attention to obtain the same effect.

To use a mutex, you have to create one, you have to acquire ownership of it and then you have to release it (when you're through with it).  These are all extra work and care you have to pay to the mutex in order to ensure one thread will not run when the other is running.  This is the same result you get by simply using the one function, WaitForSingleObject.  Nothing to create!  Nothing to lock!  Nothing to release!  You simply use it!!

Besides, using a mutex can take up to a 100 times longer to process because it is a kernel object and you have to be in kernel mode to create it, etc.
Avatar of manx

ASKER

With regards to Try's solution, the comms worker thread does not entirely terminate after the command is executed.

As a comms thread, it just checks if there there is a message to be transmitted or recieved, failing which it suspends itself. It only terminates when the entire application is aboutto terminate. Thus the WaitForSingleObject which waits for thread termination would not work.

That is if I have interpreted the answer correctly.

Refering to Pig's solution, could you pls clarify, with the mutex implemented, where exactly do you down/lock the mutex? Does the mutex prevent thread execution ? Would it be the same as delcaring a gigantic critical section for the read/write process ?

Thanks for all the comments/help

regards

ManX
That class prvent execute two function inone thread if You make block upon one and same global ( for functions ) mutex. Each function that use it will be blocked while another working. Destructor of that class UnLock  mutex. I think that it is question.  If I am not right say me!
I misunderstood your question.

Upon further explanation, WaitForSinglObject would not serve the full benefit of what you're trying to achieve.  What you need is either a Critical Section, or a Mutex.

Although mutexes and critical sections do the same thing, there are some differences in how they operate:

1)  It takes almost 100 times longer to lock an "unowned mutex" than it does to lock an "unowned critical section", because the critical section can be done in user mode without involving the kernel.

2)  Mutexes can be used between Processes.  Critical sections can only be used within the same Process.

3)  You can specify a timeout when waiting on a mutex, but not a critical section.


Since you're working with just the three threads, if all are within the same Process, then you can strike out the concern of #2.

If you're going to put a time limitation on the first worker thread (i.e. the comm thread) to ascertain if any message has arrived, then discovering this fact could easily be done with a WaitForSingleObject (using either its timeout mechanism or its ability to check for something and return immediately) in order to determine whether control should be handed over to the second worker thread without using a mutex.  Consequently, concern #3 can also be struck out.

Concern #1 is the only one remaining, which then answers the question whether you should use a mutex or a critical section, and since considerable time can be saved using a critical section over a mutex, the obvious answer would point in the direction of using a critical section.  However, because a critical section does not require a kernel object, there are certain system benefits one loses by using this type of synchronization method.  You gain speed by using a critical section, but loses automatic cleanup by the system in the event the thread using the critical section crashes or fails to call the proper function before exiting the critical section.  There are pros and cons both ways, and  a lot depends on the sort of care you employ in coding your program.

Like a mutex, which is owned by the thread that last acquired it, a critical section is similarly owned by the thread that is currently using it.  To gain control of a critical section, a thread simply initialize a variable of type CRITICAL_SECTION by calling the proper function, seeks permission to enter it by calling another function, it then does its work, and when ready to exit, calls yet another function.  If, upon exiting the critical section, you are certain that you are finished using the resource, you clean the CRITICAL_SECTION structure up by calling the last of a set of functions.

The resource that a critical section protects from improper access is NOT the same kind of resource from a resource file.  The resource could be a single memory location, a data structure, a file, or anything else (including proper timing) where mutual exclusion must be enforced so that only one thread is allowed to access the resource at a time.

There could be multiple places in your application that access the shared resource.  Together, all of these pieces of code make up a single critical section.

In your case, the critical section would be in that part of your main thread where the decision is made which of the worker thread gets called.

If you have further questions, don't hesitate.
Hi,

I have been directed to this question by manix who wants to equally split the points.

I have asked manx to accept PIG's answer and award him the points, and I have posted another question for Try t claim his/her share of the points at (Q.10244404).

Hope this is ok by all.

Ian
Community Support @ Experts EXchange