00001
00002
00003 #include <pthread.h>
00004 #include <unistd.h>
00005 #include <stdexcept>
00006
00007 namespace dynamic
00008 {
00009 namespace api
00010 {
00011 class mutex : cg::not_copyable, cg::not_assignable
00012 {
00013 pthread_mutex_t m_mutex;
00014
00015 public:
00016 mutex()
00017 {
00018 pthread_mutexattr_t attr;
00019 pthread_mutexattr_init(&attr);
00020 pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
00021 pthread_mutex_init(&m_mutex, &attr);
00022 }
00023
00024 ~mutex()
00025 {
00026 pthread_mutex_destroy(&m_mutex);
00027 }
00028
00029 void lock()
00030 {
00031 pthread_mutex_lock(&m_mutex);
00032 }
00033
00034 void unlock()
00035 {
00036 pthread_mutex_unlock(&m_mutex);
00037 }
00038 };
00039
00040
00041 class thread : cg::not_assignable, cg::not_copyable
00042 {
00043 pthread_t m_thread;
00044 thread & operator=(const thread&);
00045
00046 typedef void thread_func(void*);
00047 thread_func *m_fn;
00048 void * m_data;
00049
00050 static void * thread_proc(void * param)
00051 {
00052 thread * self = static_cast<thread*>(param);
00053 self->m_fn(self->m_data);
00054 return 0;
00055 };
00056
00057 public:
00058 thread() : m_thread(0)
00059 {
00060 }
00061
00062 void run(thread_func fn, void * data)
00063 {
00064 m_fn = fn;
00065 m_data = data;
00066 pthread_attr_t attr;
00067 pthread_attr_init(&attr);
00068 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
00069 if( pthread_create(&m_thread, &attr, &thread_proc, this) )
00070 throw std::runtime_error("pthread_create failed");
00071 pthread_attr_destroy(&attr);
00072 }
00073
00074 void join()
00075 {
00076 void * status;
00077 if( pthread_join(m_thread, &status) )
00078 throw std::runtime_error("pthread_join failed");
00079 }
00080 };
00081
00082
00083 class event : cg::not_copyable, cg::not_assignable
00084 {
00085 pthread_mutex_t m_mutex;
00086 pthread_cond_t m_cond;
00087 bool m_set;
00088
00089 public:
00090 event()
00091 {
00092 if( pthread_cond_init(&m_cond, NULL) )
00093 throw std::runtime_error("pthread_cond_init");
00094 pthread_mutex_init(&m_mutex, NULL);
00095 m_set = false;
00096 }
00097
00098 ~event()
00099 {
00100 pthread_mutex_destroy(&m_mutex);
00101 pthread_cond_destroy(&m_cond);
00102 }
00103
00104 void wait()
00105 {
00106 pthread_mutex_lock(&m_mutex);
00107 if(m_set)
00108 {
00109 m_set = false;
00110 pthread_mutex_unlock(&m_mutex);
00111 return;
00112 }
00113 if( pthread_cond_wait(&m_cond, &m_mutex) )
00114 throw std::runtime_error("pthread_cond_wait failed");
00115 m_set = false;
00116 pthread_mutex_unlock( &m_mutex );
00117 }
00118
00119 void signal()
00120 {
00121 pthread_mutex_lock(&m_mutex);
00122 m_set = true;
00123 pthread_mutex_unlock(&m_mutex);
00124 if( pthread_cond_signal(&m_cond) )
00125 throw std::runtime_error("pthread_cond_signal failed");
00126 }
00127 };
00128
00129
00130 inline void sleep(int s)
00131 {
00132 ::sleep(s);
00133 }
00134
00135
00137
00138 class atomic_counter
00139 {
00140 public:
00141 atomic_counter() : m_counter(0)
00142 {
00143 }
00144
00145 int operator++()
00146 {
00147 m_mutex.lock();
00148 int r = ++m_counter;
00149 m_mutex.unlock();
00150 return r;
00151 }
00152
00153 int operator++(int)
00154 {
00155 m_mutex.lock();
00156 int r = m_counter++;
00157 m_mutex.unlock();
00158 return r;
00159 }
00160
00161 int operator--()
00162 {
00163 m_mutex.lock();
00164 int r = --m_counter;
00165 m_mutex.unlock();
00166 return r;
00167 }
00168
00169 int operator--(int)
00170 {
00171 m_mutex.lock();
00172 int r = m_counter--;
00173 m_mutex.unlock();
00174 return r;
00175 }
00176
00177 private:
00178 int m_counter;
00179 mutex m_mutex;
00180 };
00181
00182
00183 class stack : cg::not_copyable, cg::not_assignable
00184 {
00185 public:
00186 stack() : m_size(0), m_shutdown(false)
00187 {
00188 pthread_mutex_init(&m_mutex, NULL);
00189 pthread_cond_init(&m_cond, NULL);
00190 pthread_cond_init(&m_empty, NULL);
00191 }
00192
00193 ~stack()
00194 {
00195 pthread_cond_destroy(&m_empty);
00196 pthread_cond_destroy(&m_cond);
00197 pthread_mutex_destroy(&m_mutex);
00198 }
00199
00200 void push()
00201 {
00202 pthread_mutex_lock(&m_mutex);
00203 m_size++;
00204 pthread_cond_signal(&m_cond);
00205 pthread_mutex_unlock(&m_mutex);
00206 }
00207
00208 void shutdown()
00209 {
00210 pthread_mutex_lock(&m_mutex);
00211 m_shutdown = true;
00212 pthread_cond_broadcast(&m_cond);
00213 pthread_mutex_unlock(&m_mutex);
00214 }
00215
00216 bool check_shutdown()
00217 {
00218 pthread_mutex_lock(&m_mutex);
00219 bool ret = m_shutdown;
00220 pthread_mutex_unlock(&m_mutex);
00221 return ret;
00222 }
00223
00224 bool wait_pop()
00225 {
00226 pthread_mutex_lock(&m_mutex);
00227 while(m_size == 0 && !m_shutdown) pthread_cond_wait(&m_cond, &m_mutex);
00228 if(m_shutdown)
00229 {
00230 pthread_mutex_unlock(&m_mutex);
00231 return false;
00232 }
00233 --m_size;
00234 if(m_size) pthread_cond_signal(&m_cond);
00235 else pthread_cond_signal(&m_empty);
00236 pthread_mutex_unlock(&m_mutex);
00237 return true;
00238 }
00239
00240 void wait_empty()
00241 {
00242 pthread_mutex_lock(&m_mutex);
00243 while(m_size && !m_shutdown) pthread_cond_wait(&m_empty, &m_mutex);
00244 pthread_mutex_unlock(&m_mutex);
00245 }
00246
00247 private:
00248 int m_size;
00249 bool m_shutdown;
00250
00251 pthread_mutex_t m_mutex;
00252 pthread_cond_t m_cond, m_empty;
00253 };
00254 }
00255 }