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;
  }
};