I have a function which must run completely, without interruption, and return a result. If an asynch event causes it to be called again while it is still executing, that call must be blocked somehow until the first call has completed.
Mutex? Something else?
[Update]
The function is in my main form class and is invoked from two methods of the class: one handles data read from the serail port and the other handles timer expiry. Both of these appear to be running in their own threads as a call of the function from one can be interupted by a call from the other (to me, at application level, they are just components which I dropped on my main form at design time).
Maybe TCriticalSection? (but googling makes it unclear whether I need to use acquire/release or ‘enter/leave` and it also seems that since the code is in a simple function of may mainform, it will be reentrant).
Perhaps what I am asking for is a way to make code “un-reentrant”, blocking until the firsty entry is complete? Whatever the answer, I think that I am going to need a code exampel, or a UTl to one 🙁
(Note that this page gives lots of useful information (I don’t grok it all, but it looks extremely useful to others))
[Update]
This has nothing to do with GUI updating, just that each event that sends some TCOP data should recevie the response.
Although the app has a GUI – it is form based – that is only in case I wanted to show some debug info, becasue the app will run on a PC with no monitor (yes, I know that it stil has a GUI, but that is not my problem/point)
Another approach is when entering the critical function from one of the event sources (say, serial port handler), disable the other event source (expiry timer) for the duration of the call. Reenable it after the call. You’re guaranteed that the other event source cannot fire during your call because the timer has been disabled.
This is braindead simple for the case of turning off the expiry timer when you’re about to process a serial data packet. If we assume that the expiry timer is to track when nothing has been received from the serial port for some period of time, disabling the expiry timer on serial data received is appropriate. Restore/restart the expiry timer when finished processing the serial data packet.
The opposite case – receiving serial data while processing the expiry timer – may be a little trickier, since you probably don’t want to risk losing data by disabling the serial data receiver. If your serial data handler can easily be paused/resumed with no loss of data, you’re done! Otherwise, your best bet here is probably to use a boolean flag in the object instance to indicate when the critical function is executing.
If a serial data packet comes in and that flag is true, then push the serial data packet into a list to be processed later and return immediately. Set up your expiry timer handler to check that list immediately before and after returning from the critical call. If the list is non-empty, process all the items in the list. If there are data packets in the list waiting to be processed as you enter the expiry timer handler, you probably want to ignore the expiry timer expiration and just keep on chugging.
In the serial data handler, check if the list is non-empty before and after calling the critical function. Checking before will help ensure that the serial data packets are handled in the order they were received. Checking after will ensure that subsequent serial data that arrives during the processing of the current data packet will not be lost.
If there is any chance of the serial data event handler being called on a different thread, then updates to the boolean flag and list should be handled carefully in a threadsafe manner. If the serial event handler (and the expiry timer handler) are guaranteed to execute on the UI thread, then you don’t have to worry about this.