EGrabber flavors
When should the callback functions be called? From which context (i.e., which thread)? Thinking about these questions leads to the definition of several callback models:
-
The application asks the grabber: "Do you have any buffer or event for me? If yes, execute my callback function now." This is a polling, synchronous mode of operation, where callbacks are executed when the application demands it, in the application thread.
We'll refer to this callback model as on demand.
-
The application asks the grabber to create a single, dedicated thread, and to wait for events in this thread. When an event occurs, the grabber executes the corresponding callback function, also in this single callback thread.
We'll refer to this callback model as single thread.
-
The application asks the grabber to create a dedicated thread for each of its callback functions. In each of these threads, the grabber waits for a particular category of events. When an event occurs, the corresponding callback function is executed in that thread.
We'll refer to this callback model as multi thread.
These three callback models all make sense, and each one is best suited for some applications.
-
The on demand model is the simplest. Although its implementation may use worker threads, from the point of view of the user it doesn't add any thread. This means that the application doesn't need to worry about things such as thread synchronization, mutexes, etc.
-
If the user wants a dedicated callback thread, the single thread model creates it for him.
When we have only one thread, things are simple. In this model, the grabber is used in (at least) two threads, so we need to start worrying about synchronization and shared data.
-
In the multi thread model, each category of event gets its own thread. The benefit of this is that events of one type (and the execution of their callback functions) don't delay notifications of events of other types. For example, a thread doing heavy image processing in
onNewBufferEvent
will not delay the notification of CIC events byonCicEvent
(e.g., events indicating that the exposure is complete and that the object or camera can be moved).In this model, the grabber is used in several thread, so the need for synchronization is present as it is in the single thread model.
Of course, the application must also be aware that it might receive notifications for events of type X that are older than notifications of events of type Y that have already been received and processed. After all, this is the differentiating factor between the single thread and multi thread models.
To give the user maximum flexibility, we support all three callback models. This is why
Euresys::EGrabber
exists in different flavors. So far, we have
eluded the meaning of the angle brackets in EGrabber<>
. The
EGrabber
class is actually a template class, i.e., a class
that is parameterized by another type:
-
In this case, the template parameter is the callback model to use: one of
CallbackOnDemand
,CallbackSingleThread
orCallbackMultiThread
. -
The empty
<>
are used to select the default template parameter, which isCallbackOnDemand
. -
The types of grabber that can be instantiated are:
EGrabber<CallbackOnDemand>
EGrabber<CallbackSingleThread>
EGrabber<CallbackMultiThread>
EGrabber<>
which is equivalent toEGrabber<CallbackOnDemand>
-
The
EGrabber
header file also defines the following type aliases (synonyms):typedef EGrabber<CallbackOnDemand> EGrabberCallbackOnDemand; typedef EGrabber<CallbackSingleThread> EGrabberCallbackSingleThread; typedef EGrabber<CallbackMultiThread> EGrabberCallbackMultiThread;
-
The .NET generics don't quite match the C++ templates, so in .NET the template
EGrabber
class does not exist and we must use one ofEGrabberCallbackOnDemand
,EGrabberCallbackSingleThread
orEGrabberCallbackMultiThread
.