/***********************************************
 * File: Monitor.hh
 * Author: Keith Schwarz (htiek@cs.stanford.edu)
 *
 * A lock that can wait and be signaled.  This
 * will eventually be implemented using all of
 * the following libraries:
 *
 * - C++0x
 * - Boost
 * - pthread
 * - Win32
 */
#ifndef Monitor_Included
#define Monitor_Included

#include "Lock.hh"

namespace synch {
  class Monitor: public synch::Lock {
  public:
    /**
     * Constructor: Monitor()
     * --------------------------------------------------------------
     * Constructs a new monitor.
     */
    Monitor();
    
    /**
     * Destructor: ~Monitor()
     * -------------------------------------------------------------
     * Destroys a monitor.  You should not destroy a monitor
     * that is in use as it has undefined behavior.
     */
    ~Monitor();
    
    /**
     * void lock();
     * void unlock();
     * -------------------------------------------------------------
     * Locks or unlocks the monitor.  Only one thread can own the
     * monitor at a time, and that thread is not allowed to acquire
     * the lock reentrantly.
     */
    void lock();
    void unlock();
    
    /**
     * void wait();
     * -------------------------------------------------------------
     * Unlocks the monitor, blocks until the monitor is notified,
     * then reacquires the lock.  The calling thread must own the
     * monitor before calling this function.
     */
    void wait();
    
    /**
     * void notify();
     * -------------------------------------------------------------
     * Notifies at least one waiting thread that the monitor is ready.
     * The calling thread must own the monitor before calling this
     * function.
     */
    void notify();
    
    /**
     * void notifyAll()
     * -------------------------------------------------------------
     * Notifies at least one waiting thread that the monitor is ready.
     * The calling thread must own the monitor before calling this
     * function.
     */
    void notifyAll();
    
  private:
    /* pImpl idiom to hide implementation. */
    struct Impl;
    Impl* mImpl;
  };
}

#endif
