# semaphore.h

Go to the documentation of this file.

    00001 ///
    00002 /// \file       semaphore.h
    00003 ///             Simple class implementing a semaphore using pthreads mutex and condvar.
    00004 ///
    00005
    00006 /*
    00007     Copyright (C) 2010, RealVNC Ltd.
    00008
    00009     This program is free software; you can redistribute it and/or modify
    00010     it under the terms of the GNU General Public License as published by
    00011     the Free Software Foundation; either version 2 of the License, or
    00012     (at your option) any later version.
    00013
    00014     This program is distributed in the hope that it will be useful,
    00015     but WITHOUT ANY WARRANTY; without even the implied warranty of
    00016     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
    00017
    00018     See the GNU General Public License in the COPYING file at the
    00019     root directory of this project for more details.
    00020 */
    00021
    00022 #ifndef __BARRY_SEMAPHORE_H__
    00023 #define __BARRY_SEMAPHORE_H__
    00024
    00025 #include "scoped_lock.h"
    00026 #include <pthread.h>
    00027
    00028 namespace Barry {
    00029
    00030 class semaphore
    00031 {
    00032         pthread_mutex_t *m_mutex;
    00033         pthread_cond_t *m_cv;
    00034         int m_value;
    00035 public:
    00036         semaphore(pthread_mutex_t &mutex, pthread_cond_t &cv, int value = 0)
    00037                 : m_mutex(&mutex)
    00038                 , m_cv(&cv)
    00039                 , m_value(value)
    00040         {
    00041         }
    00042
    00043         // Waits for the value of this semaphore to be greater than 0 and then
    00044         // decrements it by one before returning.
    00045         void WaitForSignal()
    00046         {
    00047                 scoped_lock lock(*m_mutex);
    00048                 while( m_value <= 0 ) {
    00049                         int ret = pthread_cond_wait(m_cv, m_mutex);
    00050                         if( ret != 0 ) {
    00051                                 throw Barry::Error("semaphore: failed to wait on condvar");
    00052                         }
    00053                 }
    00054                 --m_value;
    00055                 lock.unlock();
    00056         }
    00057
    00058         // Checks for a semaphore signal without blocking. Returns true and decrements
    00059         // the semaphore if the value is greater than 0, otherwise returns false.
    00060         bool ReceiveSignal()
    00061         {
    00062                 bool ret = false;
    00063                 scoped_lock lock(*m_mutex);
    00064                 if( m_value > 0 ) {
    00065                         --m_value;
    00066                         ret = true;
    00067                 }
    00068                 lock.unlock();
    00069                 return ret;
    00070         }
    00071
    00072         // Increments the value of this semaphore by 1, waking any sleeping threads waiting
    00073         // on this semaphore.
    00074         void Signal()
    00075         {
    00076                 scoped_lock lock(*m_mutex);
    00077                 ++m_value;
    00078                 int ret = pthread_cond_signal(m_cv);
    00079                 if( ret != 0 ) {
    00080                         throw Barry::Error("Condvar: failed to signal condvar");
    00081                 }
    00082                 lock.unlock();
    00083         }
    00084 };
    00085
    00086 } // namespace Barry
    00087
    00088 #endif
    00089