question

Upvote
Accepted
16 0 1 3

APIdisptatch mode behaviour, VA Reactor thread in EMA API

It is my understanding that when a Consumer is set to operate in APIDispatch mode (which is the default), a new internal thread is created to manage VA reactor and it dispatches messages to the callbacks on registered Consumerclient object. Now I would expect this thread to continue to run and dispatch updates as they are received from the producer. It seems like if the main run were to exit, this VA rector thread shutdowns automatically. Isn't there a need to invoke any stop() to shutdown this thread or it that functionality in the Consumer Destructor()?

In the EMA samples just to receive the callback, it seems one needs to have a sleep in the main thread to see the callback is invoked.

elektronrefinitiv-realtimeelektron-sdkrrtema-apielektron-message-apiapimulti-threading
icon clock
10 |1500

Up to 2 attachments (including images) can be used with a maximum of 5.0 MiB each and 10.0 MiB total.

Upvotes
Accepted
103 0 2 1

There seems to be two questions in this post. The first one about the need to explicitly stop / shutdown the internal EMA thread; and the other about the need for the sleep() call in the main() of the example applications.

To answer the first question... the OmmConsumer destructor does stop its own thread. Please see the OmmConsumerImpl::uninitialize() method for details. There is no need for the application to stop the internal EMA thread.

To answer the second question... the example applications provided with the EMA are written to demonstrate features or usage of the EMA. The sleep() call is used to make sure that the application does not automatically exit right after opening items. The sleep() call may be replaced by another task the application may do while waiting to receive item responses. The sleep() was chosen to keep the example applications focused on the usage of the EMA.

Hope this helps.

icon clock
10 |1500

Up to 2 attachments (including images) can be used with a maximum of 5.0 MiB each and 10.0 MiB total.

Upvotes
1.2k 23 28 42

Pending an update to the developers guide: if one considers a typical Windows App architecture then expect the `OmmConsumer` to be used RAII style around an event loop, e.g.

AppClient client;
OmmConsumer consumer (OmmConsumerConfig().host ("localhost:14002").username ("user"));
consumer.registerClient (ReqMsg().serviceName ("hEDD").name ("TIBX.O"), client);
while ((bRet = GetMessage (&msg, NULL, 0, 0)) != 0) { 
  if (bRet != -1) {
    TranslateMessage(&msg); 
    DispatchMessage(&msg); 
  }
} 
// program is now terminating ...

Replacing the `GetMessage` loop as appropriate for Qt, Gtk or whatever UI toolkit is being used.

For server applications that do not integrate with another event loop you will have to create your own wait mechanism, for example with Win32:

WaitForSingleObject (exit_handle, INFINITE);

Set the object through a Control+C break handler or similar.

For Unix applications one may wish to use a conditional variable, e.g.

std::mutex m;
std::condition_variable cv;
bool ready = false;
std::unique_lock<std::mutex> lk (m);
cv.wait (lk, []{return ready;});
std::cout << "main() is terminating\n";

Then inside an event callback one can raise the condition to terminate:

{
  std::lock_guard<std::mutex> lk(m);
  ready = true;
  std::cout << "event_handler() terminating application\n";
}
cv.notify_one();

If one digs around the tutorial code provided some present usage of explicit dispatch control, I found the following:

AppClient client;
OmmConsumer consumer (OmmConsumerConfig().username ("user").operationModel (OmmConsumerConfig::UserDispatchEnum));
consumer.registerClient (ReqMsg().name ("TIBX.O").serviceName ("hEDD"), client);
for (;;)
  consumer.dispatch( 10 );    // calls to onRefreshMsg(), onUpdateMsg(), or onStatusMsg() execute on this thread
icon clock
10 |1500

Up to 2 attachments (including images) can be used with a maximum of 5.0 MiB each and 10.0 MiB total.

Upvotes
103 0 2 1

The EMA is written from the perspective of the "common usage", common across all the supported platforms. The EMA does not favor any OS, neither Windows or Linux. The same applications, e.g. the same code, will work on Linux and Windows and they will work the same way.

The very first example in the above post, is a little misleading. The EMA does not require, as presented in this example, usage of the Windows message loop. The usage of the Windows message loop is absolutely a choice of the application. For example, if the application, on its own, needs it, then the application is free to use it. It is worth to mention that the EMA does not send or receive any messages to / from the Windows OS. Furthermore, the EMA does not prevent users from integrating the Windows messaging in their applications.

icon clock
10 |1500

Up to 2 attachments (including images) can be used with a maximum of 5.0 MiB each and 10.0 MiB total.

Upvotes
9.7k 49 38 60

To provide additional content around EMA dispatch and thread usage, the EMA Tutorials have been updated to provide a brief overview of operation which includes links to relevant documentation.

Refer to the Message Processing - dispatch section within the EMA Consumer - Requesting MarkePrice Data tutorial.

icon clock
10 |1500

Up to 2 attachments (including images) can be used with a maximum of 5.0 MiB each and 10.0 MiB total.

Click below to post an Idea Post Idea