UtiLite  0.3.1
A lite utilities library
include/utilite/USemaphore.h
00001 /*
00002 *  utilite is a cross-platform library with
00003 *  useful utilities for fast and small developing.
00004 *  Copyright (C) 2010  Mathieu Labbe
00005 *
00006 *  utilite is free library: you can redistribute it and/or modify
00007 *  it under the terms of the GNU Lesser General Public License as published by
00008 *  the Free Software Foundation, either version 3 of the License, or
00009 *  (at your option) any later version.
00010 *
00011 *  utilite is distributed in the hope that it will be useful,
00012 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014 *  GNU Lesser General Public License for more details.
00015 *
00016 *  You should have received a copy of the GNU Lesser General Public License
00017 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
00018 */
00019 
00020 /*
00021  * Originally written by Phillip Sitbon
00022  *  Copyright 2003
00023  */
00024 
00025 #ifndef USEMAPHORE_H
00026 #define USEMAPHORE_H
00027 
00028 #include <errno.h>
00029 
00030 #ifdef WIN32
00031 #include "utilite/Win32/UWin32.h"
00032 #define SEM_VALUE_MAX ((int) ((~0u) >> 1))
00033 #else
00034 #include <pthread.h>
00035 #endif
00036 
00053 class USemaphore
00054 {
00055 public:
00060         USemaphore( int initValue = 0 )
00061         {
00062 #ifdef WIN32
00063                 S = CreateSemaphore(0,initValue,SEM_VALUE_MAX,0);
00064 #else
00065                 _available = initValue;
00066                 pthread_mutex_init(&_waitMutex, NULL);
00067                 pthread_cond_init(&_cond, NULL);
00068 #endif
00069         }
00070 
00071         virtual ~USemaphore()
00072         {
00073 #ifdef WIN32
00074                 CloseHandle(S);
00075 #else
00076                 pthread_cond_destroy(&_cond);
00077                 pthread_mutex_destroy(&_waitMutex);
00078 #endif
00079         }
00080 
00087 #ifdef WIN32
00088         void acquire(int n = 1) const
00089         {
00090                 while(n-- > 0)
00091                 {
00092                         WaitForSingleObject((HANDLE)S,INFINITE);
00093                 }
00094 #else
00095         void acquire(int n = 1)
00096         {
00097                 pthread_mutex_lock(&_waitMutex);
00098                 while (n > _available)
00099                 {
00100                         while(1)
00101                         {
00102                                 pthread_cond_wait(&_cond, &_waitMutex);
00103                                 break;
00104                         }
00105                 }
00106                 _available -= n;
00107                 pthread_mutex_unlock(&_waitMutex);
00108 #endif
00109         }
00110 
00111         /*
00112          * Try to acquire the semaphore, not a blocking call.
00113          * @return false if the semaphore can't be taken without waiting (value <= 0), true otherwise
00114          */
00115 #ifdef WIN32
00116         int acquireTry() const
00117         {
00118                 return ((WaitForSingleObject((HANDLE)S,INFINITE)==WAIT_OBJECT_0)?0:EAGAIN);
00119 #else
00120         int acquireTry(int n)
00121         {
00122                 pthread_mutex_lock(&_waitMutex);
00123                 if(n > _available)
00124                 {
00125                         pthread_mutex_unlock(&_waitMutex);
00126                         return false;
00127                 }
00128                 _available -= n;
00129                 pthread_mutex_unlock(&_waitMutex);
00130                 return true;
00131 #endif
00132         }
00133 
00138 #ifdef WIN32
00139         int release(int n = 1) const
00140         {
00141                 return (ReleaseSemaphore((HANDLE)S,n,0)?0:ERANGE);
00142 #else
00143         void release(int n = 1)
00144         {
00145                 pthread_mutex_lock(&_waitMutex);
00146                 _available += n;
00147                 pthread_cond_broadcast(&_cond);
00148                 pthread_mutex_unlock(&_waitMutex);
00149 #endif
00150         }
00151 
00156 #ifdef WIN32
00157         int value() const
00158         {
00159                 LONG V = -1; ReleaseSemaphore((HANDLE)S,0,&V); return V;
00160 #else
00161         int value()
00162         {
00163                 int value = 0;
00164                 pthread_mutex_lock(&_waitMutex);
00165                 value = _available;
00166                 pthread_mutex_unlock(&_waitMutex);
00167                 return value;
00168 #endif
00169         }
00170 
00171 #ifdef WIN32
00172         /*
00173          * Reset the semaphore count.
00174          * @param init the initial value
00175          * TODO implement on posix ?
00176          */
00177         void reset( int init = 0 )
00178         {
00179                 CloseHandle(S);
00180                 S = CreateSemaphore(0,init,SEM_VALUE_MAX,0);
00181         }
00182 #endif
00183 
00184 private:
00185 #ifdef WIN32
00186         HANDLE S;
00187 #else
00188         pthread_mutex_t _waitMutex;
00189         pthread_cond_t _cond;
00190         int _available;
00191 #endif
00192         void operator=(const USemaphore &S){}
00193         USemaphore(const USemaphore &S){}
00194 };
00195 
00196 #endif // USEMAPHORE_H
 All Classes Files Functions Variables Enumerations Friends Defines