- Undocumented Matlab - https://undocumentedmatlab.com -
Blocked wait with timeout for asynchronous events
Posted By Yair Altman On May 13, 2018 | No Comments
Readers of this website may have noticed that I have recently added an IQML section [1] to the website’s top menu bar. IQML is a software connector that connects Matlab to DTN’s IQFeed, a financial data-feed of live and historic market data. IQFeed, like most other data-feed providers, sends its data in asynchronous messages, which need to be processed one at a time by the receiving client program (Matlab in this case). I wanted IQML to provide users with two complementary modes of operation:
[1]
Implementing streaming mode is relatively simple in general – all we need to do is ensure that the underlying connector object passes the incoming server messages to the relevant Matlab function for processing, and ensure that the user has some external way to access this processed data in Matlab memory (in practice making the connector object pass incoming data messages as Matlab callback events may be non-trivial, but that’s a separate matter – read here [2] for details).
In today’s article I’ll explain how we can implement a blocking mode in Matlab. It may sound difficult but it turns out to be relatively simple.
I had several requirements/criteria for my blocked-wait implementation:
The basic idea is to use Matlab’s builtin waitfor, as I explained in another post [3] back in 2012. If our underlying connector object has some settable boolean property (e.g., Done
) then we can set this property in our event callback, and then waitfor(object,'Done')
. The timeout mechanism is implemented using a dedicated timer object, as follows:
% Wait for data updates to complete (isDone = false if timeout, true if event has arrived)
function isDone = waitForDone(object, timeout)
% Initialize: timeout flag = false
object.setDone(false);
% Create and start the separate timeout timer thread
hTimer = timer('TimerFcn',@(h,e)object.setDone(true), 'StartDelay',timeout);
start(hTimer);
% Wait for the object property to change or for timeout, whichever comes first
waitfor(object,'Done');
% waitfor is over - either because of timeout or because the data changed
% To determine which, check whether the timer callback was activated
isDone = isvalid(hTimer) && hTimer.TasksExecuted == 0;
% Delete the timer object
try stop(hTimer); catch, end
try delete(hTimer); catch, end
% Return the flag indicating whether or not timeout was reached
end % waitForDone
where the event callback is responsible for invoking object.setDone(true)
when the server data arrives. The usage would then be similar to this:
requestDataFromServer();
if isBlockingMode
% Blocking mode - wait for data or timeout (whichever comes first)
isDone = waitForDone(object, 10.0); % wait up to 10 secs for data to arrive
if ~isDone % indicates a timeout
fprintf(2, 'No server data has arrived within the specified timeout period!\n')
end
else
% Non-blocking (streaming) mode - continue with regular processing
end
But what can we do if we don’t have such a Done
property in our underlying object, or if we do not have programmatic access to it?
We could create a new non-visible figure and then waitfor one of its properties (e.g. Resize
). The property would be initialized to 'off'
, and within both the event and timer callbacks we would set it to 'on'
, and then waitfor(hFigure,'Resize','on')
. However, figures, even if non-visible, are quite heavy objects in terms of both memory, UI resources, and performance.
It would be preferable to use a much lighter-weight object, as long as it abides by the other criteria above. Luckily, there are numerous such objects in Java, which is bundled in every Matlab since 2000, on every Matlab platform. As long as we choose a small Java object that has existed forever, we should be fine. For example, we could use a simple javax.swing.JButton
and its boolean property Enabled
:
hSemaphore = handle(javax.swing.JButton); % waitfor() expects a handle() object, not a "naked" Java reference
% Wait for data updates to complete (isDone = false if timeout, true if event has arrived)
function isDone = waitForDone(hSemaphore, timeout)
% Initialize: timeout flag = false
hSemaphore.setEnabled(false);
% Create and start the separate timeout timer thread
hTimer = timer('TimerFcn',@(h,e)hSemaphore.setEnabled(true), 'StartDelay',timeout);
start(hTimer);
% Wait for the object property to change or for timeout, whichever comes first
waitfor(hSemaphore,'Enabled');
% waitfor is over - either because of timeout or because the data changed
% To determine which, check whether the timer callback was activated
isDone = isvalid(hTimer) && hTimer.TasksExecuted == 0;
% Delete the timer object
try stop(hTimer); catch, end
try delete(hTimer); catch, end
% Return the flag indicating whether or not timeout was reached
end % waitForDone
In this implementation, we would need to pass the hSemaphore
object handle to the event callback, so that it would be able to invoke hSemaphore.setEnabled(true)
when the server data has arrived.
Under the hood, note that Enabled
is not a true “property” of javax.swing.JButton
, but rather exposes two simple public getter/setter methods (setEnabled() and isEnabled()), which Matlab interprets as a “property”. For all intents and purposes, in our Matlab code we can treat Enabled
as a property of javax.swing.JButton
, including its use by Matlab’s builtin waitfor function.
There is a light overhead to this: on my laptop the waitfor function returns ~20 mSecs after the invocation of hSemaphore.setEnabled(true)
in the timer or event callback – in many cases this overhead is negligible compared to the networking latencies for the blocked data request. When event reactivity is of utmost importance, users can always use streaming (non-blocking) mode, and process the incoming data events immediately in a callback.
Of course, it would have been best if MathWorks would add a timeout option and return value to Matlab’s builtin waitfor function, similar to my waitForDone
function – this would significantly simplify the code above. But until this happens, you can use waitForDone
pretty-much as-is. I have used similar combinations of blocking and streaming modes with multiple other connectors that I implemented over the years (Interactive Brokers, CQG, Bloomberg and Reuters for example), and the bottom line is that it actually works well in practice.
Let me know [4] if you’d like me to assist with your own Matlab project or data connector, either developing it from scratch or improving your existing code. I will be visiting Boston and New York in early June and would be happy to meet you in person to discuss your specific needs.
Categories: Java, Listeners, Low risk of breaking in future versions, Memory
Article printed from Undocumented Matlab: https://undocumentedmatlab.com
URL to article: https://undocumentedmatlab.com/articles/blocked-wait-with-timeout-for-asynchronous-events
URLs in this post:
[1] IQML section: http://undocumentedmatlab.com/iqml
[2] read here: http://undocumentedmatlab.com/blog/matlab-callbacks-for-java-events
[3] another post: http://undocumentedmatlab.com/blog/waiting-for-asynchronous-events
[4] Let me know: http://undocumentedmatlab.com/consulting
[5] Waiting for asynchronous events : https://undocumentedmatlab.com/articles/waiting-for-asynchronous-events
[6] UDD Events and Listeners : https://undocumentedmatlab.com/articles/udd-events-and-listeners
[7] Matlab callbacks for Java events : https://undocumentedmatlab.com/articles/matlab-callbacks-for-java-events
[8] Detecting window focus events : https://undocumentedmatlab.com/articles/detecting-window-focus-events
[9] Undocumented HG2 graphics events : https://undocumentedmatlab.com/articles/undocumented-hg2-graphics-events
[10] Matlab callbacks for Java events in R2014a : https://undocumentedmatlab.com/articles/matlab-callbacks-for-java-events-in-r2014a
Click here to print.
Copyright © Yair Altman - Undocumented Matlab. All rights reserved.