Fusion Capital Sophis v7: how to listen to coherency events in a batch/server mode?
Feb
2
Written by:
2/2/2016 1:49 PM
Some days ago, I talked about the possibility to use the Sophis.Core.Data, Sophis.Event.Core and Sophis.Event.Risque assemblies, in order to listen to specific events for toolkit columns performance optimizations. I've tried to use the same mechanism in a batch, using the following code :
class
Program
{
static
void
ProcessEvent(Sophis.Event.IEvent myEvent,
ref
bool
bProcess)
{
}
static
void
Main(
string
[] args)
{
CSMApi _api =
new
CSMApi();
try
{
_api.Initialise();
}
catch
(Exception e)
{
return
;
}
Sophis.Event.SophisEventHandler _handler =
new
Sophis.Event.SophisEventHandler(ProcessEvent);
Sophis.Event.SophisEventManager.Instance.AddHandler(_handler, Sophis.Event.Thread.MainProcess, Sophis.Event.Layer.Model);
bool
_stop =
false
;
while
(!_stop)
{
Sophis.Event.SophisEventManager.Instance.Dispatch();
System.Threading.Thread.Sleep(500);
}
Unfortunately, this code does not work as is. Putting a break point in the ProcessEvents method shows that it is never called, even if messages are received and processed. The goal of this post is to explain how it works and what it is missing.
First, in order to resolve it, I took a look at the disassembly code. I've found that for some reason, the handler was not called due to some key not found in a map. After some investigation, I've decided to test the code in C++. I knew that the Event Manager was exported in C++, whith the EventHandler callback, in the low level toolkit. I've tried first the following code:
class
EventHandlerImpl :
public
sophis::event::ISEventHandler
{
public
:
EventHandlerImpl()
{
}
// Return the name of the handler. Used for log purpose.
virtual
_STL::string GetName()
const
{
return
"ITQuants::EventHandler"
;
}
// Called each time an event is received.
// If deleteEvent is set to true, the event is deleted
// and other handlers won't be called for this event.
virtual
void
HandleEvent(
const
sophis::event::ISEvent & event,
bool
& deleteEvent)
{
try
{
Sophis::Event::IEvent^ _event = Sophis::Event::EventModel::CreateSophisEvent(event);
ITQuants::EventHandler::Global::HandleEvent(_event,deleteEvent);
}
catch
(System::Exception^ e)
{
System::String^ _msg = e->Message;
}
}
};
static
EventHandlerImpl* m_handler = NULL;
void
NativeGlobal::Register()
{
if
(m_handler==NULL)
{
m_handler =
new
EventHandlerImpl();
sophis::event::gEvtMgr.AddHandler(*m_handler,sophis::event::eThread_MainProcess,sophis::event::eLayer_Model);
}
}
Putting a breakpoint in the C++ HandleEvent method, I've seen that the callback was right called during the call of the Dispatch method. Unfortunately, the EventModel::CreateSophisEvent method fails, with an exception indicating that the key was not found. Taking a look at the content of this method, I've found a method AddEventType, that permits to link the what to the Type of class. Such a dictionary is initialized in some Initialize method. Finally, I've found the missing calls: Sophis.Event.EventModelRisque.Initialize and EventModelDRT.Initialize.
The following code works finally right:
class
Program
{
static
void
ProcessEvent(Sophis.Event.IEvent myEvent,
ref
bool
bProcess)
{
}
static
void
Main(
string
[] args)
{
CSMApi _api =
new
CSMApi();
try
{
_api.Initialise();
}
catch
(Exception e)
{
return
;
}
Sophis.Event.EventModelRisque.Initialize();
Sophis.Event.EventModelDRT.Initialize();
Sophis.Event.SophisEventHandler _handler =
new
Sophis.Event.SophisEventHandler(ProcessEvent);
Sophis.Event.SophisEventManager.Instance.AddHandler(_handler, Sophis.Event.Thread.MainProcess, Sophis.Event.Layer.Model);
bool
_stop =
false
;
while
(!_stop)
{
Sophis.Event.SophisEventManager.Instance.Dispatch();
System.Threading.Thread.Sleep(500);
}
try
{
_api.Dispose();
}
catch
(Exception e)
{
}