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