Listing 2: Examples of the Guard Idiom in use
// Simple Locking Scope
{
// Create a Guard that acts as a classical ScopedLock
Guard<Mutex> g1(m);
// Mutex is acquried, access to this region is serialized
}
// Nested Locking Scope
{
// Create a Guard that acts as a classical ScopedLock
Guard<Mutex> g1(m);
// Mutex is acquired, access to this region is serialized
{
// Create a Guard that has a nested locking scope, creating an
// opening in the lock scope from g1
Guard<Mutex, NestedScope> g2(g1);
// Mutex is released, access to this region is NOT serialized
}
// Mutex is acquried, access to this region is serialized
}
// Overlapped Locking Scope
{
// Create a Guard that acts as a classical ScopedLock
Guard<Mutex> g1(m1);
// Mutex m1 is acquired, access to this region is protected
// by m1
// Create a Guard that has an Overalapped locking scope
Guard<Mutex, OverlappedScope> g2(g1, m2);
// The serialization focus has shifted, Mutex m1 is released,
// Mutex m2 is acquired, access to this region is protected
// by m2
}
// Transferred Locking Scope, used to create a GuardedObject
// template. A GuardedObject will automatically lock and unlock an
// internal Lockable object as each method invocation begins and ends
template <class T, class LockType = VerboseLockable>
class GuardedObject {
LockType _lock;
T _p;
class TransferedScope {
public:
template <class LockType1, class LockType2>
static void shareScope(LockHolder<LockType1>& l1,
LockHolder<LockType2>& l2) {
l1.disable();
l2.getLockable().acquire();
}
template <class LockType1>
static void createScope(LockHolder<LockType1>& l) {
// Don't acquire the lock when scope the Guard is created
}
template <class LockType1>
static void destroyScope(LockHolder<LockType1>& l) {
l.getLockable().release();
}
};
class Proxy : Guard<LockType, TransferedScope> {
T& _object;
public:
Proxy(LockType& lock, T& object) :
Guard<LockType, TransferedScope>(lock), _object(object) { }
T* operator->() {
return &_object;
}
};
GuardedObject();
GuardedObject& operator=(const GuardedObject&);
public:
Proxy operator->() {
Proxy p(_lock, _p);
return p;
}
};