Stxxl  1.3.2
semaphore.h
1 /***************************************************************************
2  * include/stxxl/bits/common/semaphore.h
3  *
4  * Part of the STXXL. See http://stxxl.sourceforge.net
5  *
6  * Copyright (C) 2002 Roman Dementiev <[email protected]>
7  *
8  * Distributed under the Boost Software License, Version 1.0.
9  * (See accompanying file LICENSE_1_0.txt or copy at
10  * http://www.boost.org/LICENSE_1_0.txt)
11  **************************************************************************/
12 
13 #ifndef STXXL_SEMAPHORE_HEADER
14 #define STXXL_SEMAPHORE_HEADER
15 
16 #ifdef STXXL_BOOST_THREADS
17  #include <boost/thread/mutex.hpp>
18  #include <boost/thread/condition.hpp>
19 #else
20  #include <pthread.h>
21 #endif
22 
23 #include <stxxl/bits/noncopyable.h>
24 #include <stxxl/bits/common/error_handling.h>
25 
26 
27 __STXXL_BEGIN_NAMESPACE
28 
29 class semaphore : private noncopyable
30 {
31  int v;
32 #ifdef STXXL_BOOST_THREADS
33  boost::mutex mutex;
34  boost::condition cond;
35 #else
36  pthread_mutex_t mutex;
37  pthread_cond_t cond;
38 #endif
39 
40 public:
41  semaphore(int init_value = 1) : v(init_value)
42  {
43 #ifndef STXXL_BOOST_THREADS
44  check_pthread_call(pthread_mutex_init(&mutex, NULL));
45  check_pthread_call(pthread_cond_init(&cond, NULL));
46 #endif
47  }
48  ~semaphore()
49  {
50 #ifndef STXXL_BOOST_THREADS
51  int res = pthread_mutex_trylock(&mutex);
52 
53  if (res == 0 || res == EBUSY) {
54  check_pthread_call(pthread_mutex_unlock(&mutex));
55  } else
56  stxxl_function_error(resource_error);
57  check_pthread_call(pthread_mutex_destroy(&mutex));
58  check_pthread_call(pthread_cond_destroy(&cond));
59 #endif
60  }
61  // function increments the semaphore and signals any threads that
62  // are blocked waiting a change in the semaphore
63  int operator ++ (int)
64  {
65 #ifdef STXXL_BOOST_THREADS
66  boost::mutex::scoped_lock Lock(mutex);
67  int res = ++v;
68  Lock.unlock();
69  cond.notify_one();
70 #else
71  check_pthread_call(pthread_mutex_lock(&mutex));
72  int res = ++v;
73  check_pthread_call(pthread_mutex_unlock(&mutex));
74  check_pthread_call(pthread_cond_signal(&cond));
75 #endif
76  return res;
77  }
78  // function decrements the semaphore and blocks if the semaphore is
79  // <= 0 until another thread signals a change
80  int operator -- (int)
81  {
82 #ifdef STXXL_BOOST_THREADS
83  boost::mutex::scoped_lock Lock(mutex);
84  while (v <= 0)
85  cond.wait(Lock);
86 
87  int res = --v;
88 #else
89  check_pthread_call(pthread_mutex_lock(&mutex));
90  while (v <= 0)
91  check_pthread_call(pthread_cond_wait(&cond, &mutex));
92 
93  int res = --v;
94  check_pthread_call(pthread_mutex_unlock(&mutex));
95 #endif
96  return res;
97  }
98  // function does NOT block but simply decrements the semaphore
99  // should not be used instead of down -- only for programs where
100  // multiple threads must up on a semaphore before another thread
101  // can go down, i.e., allows programmer to set the semaphore to
102  // a negative value prior to using it for synchronization.
103  int decrement()
104  {
105 #ifdef STXXL_BOOST_THREADS
106  boost::mutex::scoped_lock Lock(mutex);
107  return (--v);
108 #else
109  check_pthread_call(pthread_mutex_lock(&mutex));
110  int res = --v;
111  check_pthread_call(pthread_mutex_unlock(&mutex));
112  return res;
113 #endif
114  }
115  // function returns the value of the semaphore at the time the
116  // critical section is accessed. obviously the value is not guaranteed
117  // after the function unlocks the critical section.
118  //int operator()
119  //{
120  // check_pthread_call(pthread_mutex_lock(&mutex));
121  // int res = v;
122  // check_pthread_call(pthread_mutex_unlock(&mutex));
123  // return res;
124  //};
125 };
126 
127 __STXXL_END_NAMESPACE
128 
129 #endif // !STXXL_SEMAPHORE_HEADER