/* Synch.h - a C++ class that provides a mutex and condition variable using
 * POSIX threads on Unix/Linux. The nested Scope class is used to provide
 * a scope based lock/unlock abstraction. Assuming some class X inherits
 * from the Synchronized class, a method of X would do the following to
 * acquire the lock on entry to the scope of the method and have it 
 * automatically released on exit from the scope of the method:
 *
 * #include "Sync.h"
 * ...
 * class X : public Synchronized {
 * public:
 *   ...
 *   some_method() { Synchronized::Scope mutex(this); ...; }
 *   ...
 * }; 
 */

#include <pthread.h>

class Synchronized {

    pthread_mutex_t m;  // mutex variable
    pthread_cond_t  c;  // condition variable

protected:

    /* use this class to associate the mutex lock/unlock with the scope
     * of a procedure
     */
    class Scope {
        Synchronized* obj;
    public:
        Scope(Synchronized* s) : obj(s)  { pthread_mutex_lock(&obj->m); }
        ~Scope() { pthread_mutex_unlock(&obj->m); }
    };

public:
		
    Synchronized() { 
       // initialize the mutex and condvar on construction
       pthread_mutex_init(&m, 0);
       pthread_cond_init(&c, 0);
    }

    ~Synchronized() {
	// destroy the mutex and condvar on destruction
        pthread_mutex_destroy(&m);
        pthread_cond_destroy(&c);
    }

    // map Java-like wait, notify and notifyAll onto pthread equivalents

    void wait() { pthread_cond_wait(&c, &m); }
    void notify() { pthread_cond_signal(&c); }
    void notifyAll() { pthread_cond_broadcast(&c); }
};
