SyncGuard -- Provide Critical Regions, Monitors


#include <SyncGuard.h>
 class SyncGuard {

  SyncGuard(Synchronizable& syncer);
  SyncGuard(Synchronizable& syncer, bool tryonly);

  virtual ~SyncGuard();

  dshwrapthread_t getOwner();

#define sync_self
#define sync_begin(s)
#define sync_begin2(t,s)
#define sync_end

#define sync_trybegin(s)
#define sync_trybegin2(t,s)
#define sync_tryend

#define sync_global_begin(t)
#define sync_global_end



The SyncGuard class uses a Synchronizable object to create a critical region, or monitor. Both of these synchronization primitives are mechanisms that ensure that only one thread can execute a guarded code segment at a time.

Creating a SynchGuard on a synchronizable object locks the guard. Destroying the object releases the guard. You can create more than one SyncGuard on a single Synchronizable object, and typically will.

The simplest use of SynchGuard is via its macros.

The NSCLDAQ threading system creates a global Synchronizable object that is used by all of the locking macros and constructors that don't take an explicit parameter.

Public member functions


Constructs a synchronization guard that uses the global Syncrhonizable to perform the synchronization.

SyncGuard(Synchronizable& syncer);

Creates a SyncGuard that uses syncer as its synchronization object.

SyncGuard(Synchronizable& syncer, bool tryonly);

Same as above, however if tryonly is true, and syncer is already locked, the thread continues execution.

virtual ~SyncGuard();

Destroys the guard, releasing the synchronization object.

dshwrapthread_t getOwner();

Returns the id of the thread that owns the synchronization object used by a synchronization guard. One use of this is to do a tryonly creation and then check to see if the running thread owns the object (indicating the try succeeded).

Macros . The macros below simplify the creation of critical segments of code.

void sync_self(void);

This macro is intended for use within an object that is derived from a Synchronizable. It locks the current object.

void sync_begin( Synchronizable& s );

Starts a a critical region that uses s to synchronize access.

voidsync_begin2( t , Synchronizable& s );

Same as sync_begin but t is appended to the name of the temporary Syncrhonizable the macro creates.

void sync_end(void);

Marks the end of a critical section that was begun with one of the sync macros above.

void sync_trybegin(Synchronizable& s);

This macro creates a temporary SynchGuard object constructed on s. Non-blocking access is to the guard is attempted. If successful, the code that follows the macro up until the next sync_tryend macro invocation is executed. If access to the guard could not be gotten without blocking, the code will not be executed.

void sync_trybegin2( t , Synchronizable& s );

This macro behaves the same as sync_trybegin2, however the parameter t is used to construct the name of the SyncGuard object used by the macro.

void sync_tryend(void);

Marks the end of a block of code that was synchronized using the sync_trybegin* macros.

void sync_global_begin( t );

The NSCLDAQ thread synchronization library creates a global Synchronizable object. This can do process wide synchronization on a coarse grained level. sync_global_begin constructs a temporary SyncGuard on that object and locks it. The t paramter is used to construct the name of the guard object.

void sync_global_end(void);

Destroys the SyncGuard created by lexically most recent sync_global_begin macro. This releases the synchronization object for other threads.