Reputation: 2907
What is the simplest way to wait for more objects than MAXIMUM_WAIT_OBJECTS
?
MSDN lists this:
MAXIMUM_WAIT_OBJECTS
handles, then wait on that thread plus the other handles. Use this technique to break the handles into groups of MAXIMUM_WAIT_OBJECTS
.RegisterWaitForSingleObject
to wait on each handle. A wait thread from the thread pool waits on MAXIMUM_WAIT_OBJECTS
registered objects and assigns a worker thread after the object is signaled or the time-out interval expires.But neither are them are very clear. The situation would be waiting for an array of over a thousand handles to threads.
Upvotes: 5
Views: 7226
Reputation: 141
Since Windows 8 there's a third way: You can use NT API to get IOCP completion packet when an event, semaphore or a thread handle gets signalled (thread finishes).
To do that you create this completion packet with NtCreateWaitCompletionPacket , and bind all three handles (this packet, IOCP and thread/event) together through poorly documented (but intuitive enough) NtAssociateWaitCompletionPacket. When you receive the completion, you can call it again to reestablish the association and receive the next one, when the object is signalled again.
See full example here: https://github.com/tringi/win32-iocp-events
Upvotes: 0
Reputation: 31
I encountered this limitation in WaitForMultipleObjects myself and came to the conclusion I had three alternatives:
So, having chosen option 3 - here is the code I ended up implementing ...
class CtntThread
{
public:
static DWORD WaitForMultipleObjects( DWORD, const HANDLE*, DWORD millisecs );
};
DWORD CtntThread::WaitForMultipleObjects( DWORD count, const HANDLE *pHandles, DWORD millisecs )
{
DWORD retval = WAIT_TIMEOUT;
// Check if objects need to be split up. In theory, the maximum is
// MAXIMUM_WAIT_OBJECTS, but I found this code performs slightly faster
// if the object are broken down in batches smaller than this.
if ( count > 25 )
{
// loop continuously if infinite timeout specified
do
{
// divide the batch of handles in two halves ...
DWORD split = count / 2;
DWORD wait = ( millisecs == INFINITE ? 2000 : millisecs ) / 2;
int random = rand( );
// ... and recurse down both branches in pseudo random order
for ( short branch = 0; branch < 2 && retval == WAIT_TIMEOUT; branch++ )
{
if ( random%2 == branch )
{
// recurse the lower half
retval = CtntThread::WaitForMultipleObjects( split, pHandles, wait );
}
else
{
// recurse the upper half
retval = CtntThread::WaitForMultipleObjects( count-split, pHandles+split, wait );
if ( retval >= WAIT_OBJECT_0 && retval < WAIT_OBJECT_0+split ) retval += split;
}
}
}
while ( millisecs == INFINITE && retval == WAIT_TIMEOUT );
}
else
{
// call the native win32 interface
retval = ::WaitForMultipleObjects( count, pHandles, FALSE, millisecs );
}
// done
return ( retval );
}
Upvotes: 3
Reputation: 191
If you find yourself waiting on tons of objects you might want to look into IO Completion Ports instead. For large numbers of parallel operations IOCP is much more efficient.
And the name IOCP is misleading, you can easily use IOCP for your own synchronization structures as well.
Upvotes: 8
Reputation: 37448
Have a look here.
If you need to wait on more than MAXIMUM_WAIT_OBJECTS handles, you can either create a separate thread to wait on MAXIMUM_WAIT_OBJECTS and then do a wait on these threads to finish. Using this method you can create MAXIMUM_WAIT_OBJECTS threads each of those can wait for MAXIMUM_WAIT_OBJECTS object handles.
Upvotes: 1