Stxxl
1.4.0
|
00001 /*************************************************************************** 00002 * include/stxxl/bits/common/semaphore.h 00003 * 00004 * Part of the STXXL. See http://stxxl.sourceforge.net 00005 * 00006 * Copyright (C) 2002 Roman Dementiev <dementiev@mpi-sb.mpg.de> 00007 * 00008 * Distributed under the Boost Software License, Version 1.0. 00009 * (See accompanying file LICENSE_1_0.txt or copy at 00010 * http://www.boost.org/LICENSE_1_0.txt) 00011 **************************************************************************/ 00012 00013 #ifndef STXXL_SEMAPHORE_HEADER 00014 #define STXXL_SEMAPHORE_HEADER 00015 00016 #ifdef STXXL_BOOST_THREADS 00017 #include <boost/thread/mutex.hpp> 00018 #include <boost/thread/condition.hpp> 00019 #else 00020 #include <pthread.h> 00021 #endif 00022 00023 #include <stxxl/bits/noncopyable.h> 00024 #include <stxxl/bits/common/error_handling.h> 00025 00026 00027 __STXXL_BEGIN_NAMESPACE 00028 00029 class semaphore : private noncopyable 00030 { 00031 int v; 00032 #ifdef STXXL_BOOST_THREADS 00033 boost::mutex mutex; 00034 boost::condition cond; 00035 #else 00036 pthread_mutex_t mutex; 00037 pthread_cond_t cond; 00038 #endif 00039 00040 public: 00041 semaphore(int init_value = 1) : v(init_value) 00042 { 00043 #ifndef STXXL_BOOST_THREADS 00044 check_pthread_call(pthread_mutex_init(&mutex, NULL)); 00045 check_pthread_call(pthread_cond_init(&cond, NULL)); 00046 #endif 00047 } 00048 ~semaphore() 00049 { 00050 #ifndef STXXL_BOOST_THREADS 00051 int res = pthread_mutex_trylock(&mutex); 00052 00053 if (res == 0 || res == EBUSY) { 00054 check_pthread_call(pthread_mutex_unlock(&mutex)); 00055 } else 00056 stxxl_function_error(resource_error); 00057 check_pthread_call(pthread_mutex_destroy(&mutex)); 00058 check_pthread_call(pthread_cond_destroy(&cond)); 00059 #endif 00060 } 00061 // function increments the semaphore and signals any threads that 00062 // are blocked waiting a change in the semaphore 00063 int operator ++ (int) 00064 { 00065 #ifdef STXXL_BOOST_THREADS 00066 boost::mutex::scoped_lock Lock(mutex); 00067 int res = ++v; 00068 Lock.unlock(); 00069 cond.notify_one(); 00070 #else 00071 check_pthread_call(pthread_mutex_lock(&mutex)); 00072 int res = ++v; 00073 check_pthread_call(pthread_mutex_unlock(&mutex)); 00074 check_pthread_call(pthread_cond_signal(&cond)); 00075 #endif 00076 return res; 00077 } 00078 // function decrements the semaphore and blocks if the semaphore is 00079 // <= 0 until another thread signals a change 00080 int operator -- (int) 00081 { 00082 #ifdef STXXL_BOOST_THREADS 00083 boost::mutex::scoped_lock Lock(mutex); 00084 while (v <= 0) 00085 cond.wait(Lock); 00086 00087 int res = --v; 00088 #else 00089 check_pthread_call(pthread_mutex_lock(&mutex)); 00090 while (v <= 0) 00091 check_pthread_call(pthread_cond_wait(&cond, &mutex)); 00092 00093 int res = --v; 00094 check_pthread_call(pthread_mutex_unlock(&mutex)); 00095 #endif 00096 return res; 00097 } 00098 // function does NOT block but simply decrements the semaphore 00099 // should not be used instead of down -- only for programs where 00100 // multiple threads must up on a semaphore before another thread 00101 // can go down, i.e., allows programmer to set the semaphore to 00102 // a negative value prior to using it for synchronization. 00103 int decrement() 00104 { 00105 #ifdef STXXL_BOOST_THREADS 00106 boost::mutex::scoped_lock Lock(mutex); 00107 return (--v); 00108 #else 00109 check_pthread_call(pthread_mutex_lock(&mutex)); 00110 int res = --v; 00111 check_pthread_call(pthread_mutex_unlock(&mutex)); 00112 return res; 00113 #endif 00114 } 00115 // function returns the value of the semaphore at the time the 00116 // critical section is accessed. obviously the value is not guaranteed 00117 // after the function unlocks the critical section. 00118 //int operator() 00119 //{ 00120 // check_pthread_call(pthread_mutex_lock(&mutex)); 00121 // int res = v; 00122 // check_pthread_call(pthread_mutex_unlock(&mutex)); 00123 // return res; 00124 //}; 00125 }; 00126 00127 __STXXL_END_NAMESPACE 00128 00129 #endif // !STXXL_SEMAPHORE_HEADER