The handler uses a concept of events and event listeners to notify the client code about various aspects of market data processing and deliver data to the user (e.g., receiving a security definition or a direct book update).
The SDK groups events and provides classes with virtual members (event listeners) for each group. Client code may override any or all listener members to implement the processing of a particular event.
Associating an event listener with an instance of the OnixS::CME::MDH::Handler class is called subscribing to events.
OnixS::CME::MDH::HandlerListeners stores pointers to application-owned listeners; it does not copy or delete them. Keep each listener alive while registered and until all callbacks using it have returned. A simple arrangement is to construct listeners before the Handler, stop the Handler from the control thread, then destroy the Handler before its listeners. For explicit engines, also follow Explicit engine lifetime.
Treat callback arguments as borrowed data for the duration of the call. Books and securities belong to the handler; packets, messages, entries, iterators and text views can refer to reused storage. Copy required values into owned storage before handing them to another thread. Copying a view does not copy its underlying bytes. Books are not thread-safe; a worker must not read a handler-owned book while processing continues. See Copying order book content and Network Packets and Messages.
Callbacks execute inline on the thread performing the operation that raises them:
These built-in engine rules do not establish threading guarantees for a custom engine. Replay callbacks follow the replay driver thread; see Replaying market data. Synchronize application state shared with control threads, workers or other Handlers. Inline calls can also nest: for example, an exception in a callback can immediately invoke onWarning on the same thread.
Catch application failures inside callbacks and return normally. The handler catches exceptions escaping the handler event listeners described below and continues its own processing without rolling back application work or requesting recovery. It attempts to report an OnixS::CME::MDH::Issue::UserException warning through OnixS::CME::MDH::HandlerListener::onWarning before continuing processing. Exceptions raised while reporting the callback failure are suppressed.
Exceptions escaping onWarning and onError are suppressed without another listener notification. Throwing from a callback is therefore not a way to fail start() or stop the handler.
Feed engine thread callbacks have a separate exception reporting policy; see OnixS::CME::MDH::FeedEngineThreadPoolListener.
Inspect callback arguments, read the session's unchanged settings, and copy or enqueue owned data. OnixS::CME::MDH::Handler::selectInstruments is also supported inside OnixS::CME::MDH::HandlerListener::onEndOfInstrumentRecovery when its status is OnixS::CME::MDH::RecoveryCompletionStatus::Succeeded; see Selecting securities of interest.
Defer lifecycle calls (start(), stop() and destruction), listener replacement, settings changes and instrument-cache cleanup to the control thread after the callback and any enclosing lifecycle call have returned. Reentering lifecycle operations can invalidate objects still in use by the invoking code. See Observing startup for lifecycle notification ordering. Do not recursively call the engine's process() or stop/join its worker pool from a callback. Do not wait for a worker that needs the current callback to return.
This example uses Boost.Lockfree's single-producer/single-consumer queue with one Handler and one application worker. Boost.Lockfree is an optional example dependency; you can replace it with an equivalent bounded, thread-safe queue.
It copies only the security ID and best bid into preallocated, bounded storage. If the queue is full, the callback drops the new sample and increments a counter. The worker calls take() and processes accepted samples in FIFO order. This loss policy suits optional telemetry; consumers requiring every update need their own overflow response and must not silently apply this policy to a sequence of book deltas.
Keep the queue and listener alive until the Handler is stopped and the application worker is joined. The example illustrates ownership and handoff only; book readiness still follows Interpreting a book update. For callback costs and ordering, see Keeping callbacks responsive.
The sections below describe event groups and show the correspondence among events, listeners, and the handler settings methods used to subscribe to them:
Method: OnixS::CME::MDH::HandlerListeners::handler
Usage example:
The handler invokes the event listener members during market data processing. Events reflect processing session stages like entering or leaving the recovery cycle, recovery completion status (OnixS::CME::MDH::RecoveryCompletionArgs), and resuming real-time data processing.
Method: OnixS::CME::MDH::HandlerListeners::marketData
Usage example:
The handler invokes the event listener members when it begins or ends processing various market data entities (e.g., a packet or a message).
Events are triggered only for market data accepted by the handler and according to CME's rules. The handler does not invoke members of the listener for any duplicated or out-of-order packets.
Method: OnixS::CME::MDH::HandlerListeners::security
Usage example:
Members of the given listener are invoked to reflect security-related events like the receiving of trade, security status, and order book updates.
By default, members of this listener are invoked for each security available on the channel. However, it is possible to restrict callback invocation for a set of securities using the OnixS::CME::MDH::Handler::selectInstruments member. See Selecting securities of interest for more information.
Method: OnixS::CME::MDH::HandlerListeners::feeds
Usage example:
The OnixS::CME::MDH::ChannelFeedListener members are invoked each time a feed-related event occurs.
The sample below demonstrates listening to Handler's events: