Introducing Lunchbox: Monitor< T >


We’ve recently refactored the Equalizer and Collage base library co::base into a separate library and project called Lunchbox. This post has some background on this change.

Why Lunchbox? It’s a basic ‘toolbox’ library for multi-threaded programming. This combined with the famous ‘the free lunch is over’ quote lead to the name Lunchbox.

I’ve decided to do a weekly series of posts where I present one feature/class of Lunchbox which is beyond the basic, well-documented threading primitives provided by STL and boost. Today it’s the turn of the template class Monitor.

The monitor is a higher-level primitive based on a condition variable. Lunchbox also has a Condition class which encapsulates a condition variable and associated lock. If you’re not familiar with condition variables, google it. Smarter people than me have written good articles about them, and the Lunchbox API is pretty straight-forward.

The monitor allows to observe the state of a variable in a blocking fashion. You can think of it as a blocking variable: A monitor has a value which can be incremented, decremented and set. Any thread can wait on the monitor to reach a certain value (waitEQ), to leave a certain value (waitNE), or to reach (waitGE) or undercut (waitNE) a given value. Using a monitor makes the code easier to understand and robust, as compared to using a traditional semaphore or barrier.

In Equalizer I typically use them to monitor a state for synchronization. For example, the pipe initialization needs to wait for the node to be initialized. Since these tasks are queued and executed in parallel, the pipe thread monitors the node state to pass initialization. The eq::Node has a Monitor< State > which represents its current state (stopped, running, failed, …):

enum State
{
STATE_STOPPED,
STATE_INITIALIZING,
STATE_INIT_FAILED,
STATE_RUNNING,
STATE_FAILED
};
lunchbox::Monitor< State > _state;

This monitor allows to wait on the state to reach a certain value, which is used in Node::waitInitialized to wait for the node thread to finish initialization from the pipe thread:

void Node::waitInitialized() const
{
_state.waitGE( STATE_INIT_FAILED );
}

The node state is advanced after initialization by the node main thread:

_state = initResult ? STATE_RUNNING : STATE_INIT_FAILED;

Similarly, the per-node frame synchronization during rendering is using monitors of frame numbers to synchronize the node main thread and pipe render threads.

Since the monitor is a template class, you can use it with your own data types. Monitors have become an invaluable primitive in Collage and Equalizer for thread synchronization.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s


%d bloggers like this: