event arithmetic
-
Windows 7, Visual Studio 2012, MFC, TCP/IP operations using API calls for high data rate application I am writing a TCP/IP thread to send data to a display device. It is a high data rate output utility and will use overlapped I/O and WaitForMultipleObjects(…) to detect when the outputs are complete. The event array has 23 events and the last 16 are for an array of 16 buffers used to output the data. The obvious way is to use a switch statement to detect each event returned by WaitForMultipleObjects(…). Can I do this instead? Note: All this pseudo code is for illustrative purposes only. None is expected to compile much less run.
// Array of addresses. Value of zero = no data, > 0 = address of data to send
message_pointer message_address_array[ 16 ];
…
// not shown: code to send the data and specify the event associated with that send. The overlapped
// API is expected to set the event when the I/O is complete. Presume an output is in progress or just
// completed when this Wait is reached.
event_detected = WaitForMultipleObjects(
EVENT_ARRAY_SIZE,
mp_common_data->event_array,
WAIT_FOR_ANY_EVENT,
WAIT_TIMEOUT_VALUE );
// error checking and timeout checking not shown
Switch( event_detected )
{
case EVENT_START_RUNNING:
{… break;} // several events not shown
case IO_EVENT_01: // no break;
case IO_EVENT_02: // no break; etc, etc
case IO_EVENT_16: // no break;
{
event_index = event_detected – IO_EVENT_01;
message_address_array[ event_index ] = 0; // zero = output completed
break;
}
Default {…}
}Will this concept work? Will it be faster than a separate case for each event? I think it will be easier to maintain. Or: I just thought of this: Before the switch do this:
event_index = event_detected – IO_EVENT_01;
if( event_index >= 0 && event_index <= LAST_EVENT )
message_address_array[ event_index ] = 0;
else
switch(…) etc, etcObviously there would be error checking and significant overhead code. To the core question, in either case, I would be doing event arithmetic, in a fashion. Is this concept valid? Again, this does not pretend to be working code, just some pseudo statement to illustrate a concept.
Thank you for your time If you work with telemetry, please check this bulletin board: www.irigbb.com
-
Windows 7, Visual Studio 2012, MFC, TCP/IP operations using API calls for high data rate application I am writing a TCP/IP thread to send data to a display device. It is a high data rate output utility and will use overlapped I/O and WaitForMultipleObjects(…) to detect when the outputs are complete. The event array has 23 events and the last 16 are for an array of 16 buffers used to output the data. The obvious way is to use a switch statement to detect each event returned by WaitForMultipleObjects(…). Can I do this instead? Note: All this pseudo code is for illustrative purposes only. None is expected to compile much less run.
// Array of addresses. Value of zero = no data, > 0 = address of data to send
message_pointer message_address_array[ 16 ];
…
// not shown: code to send the data and specify the event associated with that send. The overlapped
// API is expected to set the event when the I/O is complete. Presume an output is in progress or just
// completed when this Wait is reached.
event_detected = WaitForMultipleObjects(
EVENT_ARRAY_SIZE,
mp_common_data->event_array,
WAIT_FOR_ANY_EVENT,
WAIT_TIMEOUT_VALUE );
// error checking and timeout checking not shown
Switch( event_detected )
{
case EVENT_START_RUNNING:
{… break;} // several events not shown
case IO_EVENT_01: // no break;
case IO_EVENT_02: // no break; etc, etc
case IO_EVENT_16: // no break;
{
event_index = event_detected – IO_EVENT_01;
message_address_array[ event_index ] = 0; // zero = output completed
break;
}
Default {…}
}Will this concept work? Will it be faster than a separate case for each event? I think it will be easier to maintain. Or: I just thought of this: Before the switch do this:
event_index = event_detected – IO_EVENT_01;
if( event_index >= 0 && event_index <= LAST_EVENT )
message_address_array[ event_index ] = 0;
else
switch(…) etc, etcObviously there would be error checking and significant overhead code. To the core question, in either case, I would be doing event arithmetic, in a fashion. Is this concept valid? Again, this does not pretend to be working code, just some pseudo statement to illustrate a concept.
Thank you for your time If you work with telemetry, please check this bulletin board: www.irigbb.com
-
Windows 7, Visual Studio 2012, MFC, TCP/IP operations using API calls for high data rate application I am writing a TCP/IP thread to send data to a display device. It is a high data rate output utility and will use overlapped I/O and WaitForMultipleObjects(…) to detect when the outputs are complete. The event array has 23 events and the last 16 are for an array of 16 buffers used to output the data. The obvious way is to use a switch statement to detect each event returned by WaitForMultipleObjects(…). Can I do this instead? Note: All this pseudo code is for illustrative purposes only. None is expected to compile much less run.
// Array of addresses. Value of zero = no data, > 0 = address of data to send
message_pointer message_address_array[ 16 ];
…
// not shown: code to send the data and specify the event associated with that send. The overlapped
// API is expected to set the event when the I/O is complete. Presume an output is in progress or just
// completed when this Wait is reached.
event_detected = WaitForMultipleObjects(
EVENT_ARRAY_SIZE,
mp_common_data->event_array,
WAIT_FOR_ANY_EVENT,
WAIT_TIMEOUT_VALUE );
// error checking and timeout checking not shown
Switch( event_detected )
{
case EVENT_START_RUNNING:
{… break;} // several events not shown
case IO_EVENT_01: // no break;
case IO_EVENT_02: // no break; etc, etc
case IO_EVENT_16: // no break;
{
event_index = event_detected – IO_EVENT_01;
message_address_array[ event_index ] = 0; // zero = output completed
break;
}
Default {…}
}Will this concept work? Will it be faster than a separate case for each event? I think it will be easier to maintain. Or: I just thought of this: Before the switch do this:
event_index = event_detected – IO_EVENT_01;
if( event_index >= 0 && event_index <= LAST_EVENT )
message_address_array[ event_index ] = 0;
else
switch(…) etc, etcObviously there would be error checking and significant overhead code. To the core question, in either case, I would be doing event arithmetic, in a fashion. Is this concept valid? Again, this does not pretend to be working code, just some pseudo statement to illustrate a concept.
Thank you for your time If you work with telemetry, please check this bulletin board: www.irigbb.com
The logic is correct as
WAIT_OBJECT_0
,WAIT_OBJECT_0
+1, ... are basically a constants and with switch it is valid to select between constants. However if your application is a high data rate app then be careful with the "linear search" of theWaitForMultipleObjects()
function! It is actually documented (check its msdn page) that this function always returns the FIRST signaled handle from the array. This means if you have a "hyperactive" handle near the beginning of the array then the rest of the handles at higher indexes will starve. One technique to defend against this is "rotating" items in the array (or maybe a more fair algorithm is moving the currently signaled handle to the end of the array...). In case of Overlapped IO I would rather suggest using an IO completion port (shortly: IOCP) that isn't hard to plumb on top of your existing overlapped code, the difficult part is the overlapped IO that is ready in your case. -
The logic is correct as
WAIT_OBJECT_0
,WAIT_OBJECT_0
+1, ... are basically a constants and with switch it is valid to select between constants. However if your application is a high data rate app then be careful with the "linear search" of theWaitForMultipleObjects()
function! It is actually documented (check its msdn page) that this function always returns the FIRST signaled handle from the array. This means if you have a "hyperactive" handle near the beginning of the array then the rest of the handles at higher indexes will starve. One technique to defend against this is "rotating" items in the array (or maybe a more fair algorithm is moving the currently signaled handle to the end of the array...). In case of Overlapped IO I would rather suggest using an IO completion port (shortly: IOCP) that isn't hard to plumb on top of your existing overlapped code, the difficult part is the overlapped IO that is ready in your case.Thanks R.M. pasztorpisti, When I look at the MSDN page for WaitForMultipleObjects() I do not find that warning. I have seen one topic with two pages that someone found and I did not. Maybe this is one. However, I think I understand your linear search comment. This will be an almost exclusively output utility. The first N events for the Wait function will be on the lines of, Start running, Stop running, start and stop logging, etc. They will be infrequently used. I plan on 16 events for buffers to be sent out, an arbitrary starting number. The app that sends the data will use them in a strictly circular fashion. It will load the address of a buffer to send and trigger an event. The TCP/IP code in the thread will send the next buffer, the next item whose address is not zero. When an I/O completes, the event will be triggered, and the address set to zero. These events and addresses will be closely monitored to determine the average backlog of the outgoing data and to determine how well this keeps up with the incoming data. The high data rate stream is 12 megabits per second and there can be multiple stream of it from two or more sources. I have another app that runs with blocking TCP/IP code and it works, but the blocking I/O causes some difficulties. Now I am researching and designing how I will put the TCP/IP part in a separate thread. I wrote a test app that just starts the thread and get the start/stop/end messages to it. Now for the TCP part.
Thank you for your time If you work with telemetry, please check this bulletin board: www.irigbb.com
-
Thanks R.M. pasztorpisti, When I look at the MSDN page for WaitForMultipleObjects() I do not find that warning. I have seen one topic with two pages that someone found and I did not. Maybe this is one. However, I think I understand your linear search comment. This will be an almost exclusively output utility. The first N events for the Wait function will be on the lines of, Start running, Stop running, start and stop logging, etc. They will be infrequently used. I plan on 16 events for buffers to be sent out, an arbitrary starting number. The app that sends the data will use them in a strictly circular fashion. It will load the address of a buffer to send and trigger an event. The TCP/IP code in the thread will send the next buffer, the next item whose address is not zero. When an I/O completes, the event will be triggered, and the address set to zero. These events and addresses will be closely monitored to determine the average backlog of the outgoing data and to determine how well this keeps up with the incoming data. The high data rate stream is 12 megabits per second and there can be multiple stream of it from two or more sources. I have another app that runs with blocking TCP/IP code and it works, but the blocking I/O causes some difficulties. Now I am researching and designing how I will put the TCP/IP part in a separate thread. I wrote a test app that just starts the thread and get the start/stop/end messages to it. Now for the TCP part.
Thank you for your time If you work with telemetry, please check this bulletin board: www.irigbb.com
Here is that paragraph from the msdn doc: "When bWaitAll is FALSE, this function checks the handles in the array in order starting with index 0, until one of the objects is signaled. If multiple objects become signaled, the function returns the index of the first handle in the array whose object was signaled." This means, if your first handle is very active then your
WaitForMultipleObjects()
has good chances to return the first handle even if there are other similarly active signaled handles at higher indexes. You may not even notice this on a strong machines but this behavior may happen only on some slower machines with less cores... Even in that case it isn't really a "BUG", its just starvation that is about as hard to debug as timing related thread-sync issues. Although the paragraph in the msdn doc is not a warning underlined with multiple red lines it is something that can cause you a lot of headaches if your app starts to misbehave just in some special hard-to-reproduce circumstances.