views:

456

answers:

6

In C++, Windows platform, I want to execute a set of function calls as atomic so that execution doesn't switches to other threads in my process. How do I go about doing that? Any ideas, hints?

EDIT: I have a piece of code like:

someObject->Restart();

WaitForSingleObject(handle, INFINITE);

Now the Restart() function does its work asynchronously, so it returns quickly and when that someObject is restarted it sends me an event from another thread where I signal the event handle on which I'm waiting and thus continue processing. But now the problem is that before the code reaches WaitForSingleObject() part, I receive the restart completion event and I signal the event and after that WaitForSingleObject() never returns since it is not signaled again. That's why I want to execute both Restart() and WaitForSingleObject() as atomic.

+8  A: 

This is generally not possible. You can't force the OS to not switch to other threads.
What you can do is one of the following:

  • Use locks, mutexes, criticals sections or semaphores to synchronize a handful of threads that touch the same data.
  • Use basic operations that are atomic such as compare-and-exchange or atomic-add in the form of win32 api calls such as InterlockedIncrement() and InterlockedCompareExchange()
shoosh
A: 

Well, you could suspend (using SuspendThread) all other threads in the process, but I suppose you should rethink design of your program.

Kirill V. Lyadvinsky
SuspendThread is considered dodgy behaviour by many people, who think only Debuggers and Garbage Collectors implementations should be suspending threads.
Warren P
+5  A: 

You don't want all threads to wait, you just want to wait for the new thread to be done, without the risk of missing the signal. This can be done using a semaphore.

Create a semaphore known by both this code and the code eventually executed by Restart, using CreateSemaphore(NULL,0,1,NULL). In the code you've shown, you'll still use WaitforSingleObject to wait for your semaphore. When the thread executing the Release code is done with it's work, have it call ReleaseSemaphore.

If ReleaseSemaphore is called first, WaitforSingleObject will let you pass immediately. If WaitforSingleObject is called first, it will wait for ReleaseSemaphore.

MSDN should also help you.

Michael Madsen
+2  A: 

A general solution to lost event race is a counting semaphore.

Nikolai N Fetissov
+1  A: 

Are you using PulseEvent() to signal your handle? If so, that's the problem.

According to MSDN,

If no threads are waiting, or if no thread can be released immediately, PulseEvent simply sets the event object's state to nonsignaled and returns.

So if the handle is signaled before you wait on it, the handle is placed immediately in the nonsignaled state by PulseEvent(). That would appear to be why your are "missing" the event. To correct this, replace PulseEvent() with SetEvent().

With this scenario, though, you may need to reset the event after the wait is complete. This of course depends on if this code is executed more than once during the lifetime of your application. Assuming your waiting thread is the only thread that is waiting on the handle, use CreateEvent() to create an auto reset event. This will automatically reset the handle after your waiting thread is released, making it automatically available for the next time through.

Matt Davis
A: 

Although I worry about your design in general (ie you are making concurrent tasks sequential, thus losing all the benefits of the hard work to make it concurrent), I think I see the simple solution.

Change your event handle to be MANUAL RESET instead of AUTORESET. (see CreateEvent).

Then you won't miss the signal. After WaitForSingleObject(...), call ResetEvent().

EDIT: forget what I just said. That won't work. see comments below.

tony
This will not fix the problem. If he is using an auto-reset event already, the event remains signaled until a waiting thread is released. If there are no waiting threads, the event remains signaled until there is one. At that point, the thread is immediately released, and the event is reset. See the MSDN documentation on CreateEvent: http://msdn.microsoft.com/en-us/library/ms682396(VS.85).aspx
Matt Davis
Oh, your right. I forgot.So he must be doing something wrong. Either some other thread is also waiting on the object, or he's using the broken PulseEvent or something.
tony