00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #ifndef _BL_THREAD_H_
00024 #define _BL_THREAD_H_
00025
00026
00027
00028
00029
00030
00031
00032 #include <Utility.H>
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042 extern "C"
00043 {
00044 typedef void* (*Thread_Function)(void*);
00045 }
00046
00047 class FunctionThread;
00048 class Mutex;
00049 class ConditionVariable;
00050
00051 class Barrier;
00052 class SingleBarrier;
00053 class Semaphore;
00054 class SemaphoreB;
00055 class Gate;
00056
00057 template <class M> class Lock;
00058 template <class M> class TryLock;
00059
00060 template <> class Lock<Semaphore>;
00061
00062 template <class T, class M> class SafeVariable;
00063 template <class T> class ThreadSpecificData;
00064 template <> class ThreadSpecificData<void>;
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078 class Mutex
00079 {
00080 public:
00081 class Implementation;
00082 Mutex();
00083 virtual ~Mutex();
00084 void lock();
00085 void unlock();
00086 bool trylock();
00087 private:
00088 Mutex(const Mutex&);
00089 void operator=(const Mutex&);
00090 void* operator new(size_t size);
00091 protected:
00092 Implementation* m_impl;
00093 };
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127 template <class M = Mutex>
00128 class Lock
00129 {
00130 public:
00131 explicit Lock(M& mutex);
00132 ~Lock();
00133 private:
00134 Lock(const Lock&);
00135 void operator=(const Lock&);
00136 void* operator new(size_t size);
00137 M& m_mutex;
00138 };
00139
00140 template <class M>
00141 Lock<M>::Lock (M& mutex)
00142 : m_mutex(mutex)
00143 {
00144 m_mutex.lock();
00145 }
00146
00147 template <class M>
00148 Lock<M>::~Lock()
00149 {
00150 m_mutex.unlock();
00151 }
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187 template <class M = Mutex>
00188 class TryLock
00189 {
00190 public:
00191 explicit TryLock(M& mutex);
00192 ~TryLock();
00193 bool locked() const;
00194 private:
00195 TryLock(const TryLock&);
00196 void operator=(const TryLock&);
00197 void* operator new(size_t size);
00198 M& m_mutex;
00199 bool m_locked;
00200 };
00201
00202
00203 template <class M>
00204 TryLock<M>::TryLock(M& mutex)
00205 : m_mutex(mutex), m_locked(mutex.trylock())
00206 {
00207 }
00208
00209 template <class M>
00210 TryLock<M>::~TryLock()
00211 {
00212 if ( m_locked )
00213 {
00214 m_mutex.unlock();
00215 }
00216 }
00217
00218 template <class M>
00219 bool
00220 TryLock<M>::locked() const
00221 {
00222 return m_locked;
00223 }
00224
00225
00226
00227
00228
00229
00230 class ConditionVariable
00231 {
00232 public:
00233 class Implementation;
00234 ConditionVariable();
00235 ~ConditionVariable();
00236 void signal();
00237 void broadcast();
00238 void wait();
00239 void lock();
00240 void unlock();
00241 bool trylock();
00242 private:
00243 ConditionVariable(const ConditionVariable&);
00244 void operator=(const ConditionVariable&);
00245 Implementation* m_impl;
00246 };
00247
00248
00249
00250
00251
00252
00253 class Barrier
00254 : protected ConditionVariable
00255 {
00256 public:
00257 explicit Barrier(int cnt = 0);
00258 void init(int cnt);
00259 void wait();
00260 private:
00261 Barrier(const Barrier&);
00262 void operator=(const Barrier&);
00263 int count;
00264 int n_sleepers;
00265 bool releasing;
00266 };
00267
00268
00269
00270
00271
00272
00273 class Semaphore
00274 : protected ConditionVariable
00275 {
00276 public:
00277 explicit Semaphore(int val_ = 1);
00278 void wait();
00279 bool trywait();
00280 void post();
00281 private:
00282 Semaphore(const Semaphore&);
00283 void operator=(const Semaphore&);
00284 int value;
00285 };
00286
00287 template <>
00288 class Lock<Semaphore>
00289 {
00290 public:
00291 explicit Lock(Semaphore& sem_);
00292 ~Lock();
00293 private:
00294 Semaphore& sem;
00295 };
00296
00297
00298
00299
00300
00301
00302 class SemaphoreB
00303 : protected ConditionVariable
00304 {
00305 public:
00306 explicit SemaphoreB(int val_ = 1);
00307 int down();
00308 int up();
00309 int value();
00310 int decrement();
00311 private:
00312 SemaphoreB(const SemaphoreB&);
00313 void operator=(const SemaphoreB&);
00314 int val;
00315 };
00316
00317
00318
00319
00320
00321
00322 class SingleBarrier
00323 : protected ConditionVariable
00324 {
00325 public:
00326 explicit SingleBarrier(int);
00327 void wait();
00328 void post();
00329 private:
00330 SingleBarrier(const SingleBarrier&);
00331 void operator=(const SingleBarrier&);
00332 int count;
00333 int n_posters;
00334 int n_waiters;
00335 bool releasing;
00336 };
00337
00338
00339
00340
00341
00342
00343 class Gate
00344 : protected ConditionVariable
00345 {
00346 public:
00347 Gate();
00348 void open();
00349 void close();
00350 void release();
00351 void wait();
00352 private:
00353 Gate(const Gate&);
00354 void operator=(const Gate&);
00355 bool closed;
00356 };
00357
00358
00359
00360
00361
00362
00363 template <class T, class M = Mutex>
00364 class SafeVariable
00365 {
00366 public:
00367 void set(const T& n);
00368 const T get() const;
00369
00370 SafeVariable& operator=(const T& n);
00371 operator const T() const;
00372 private:
00373 T val;
00374 mutable M m;
00375 };
00376
00377 template <class T, class M>
00378 void
00379 SafeVariable<T,M>::set(const T& n)
00380 {
00381 m.lock();
00382 val = n;
00383 m.unlock();
00384 }
00385
00386 template < class T, class M>
00387 const T
00388 SafeVariable<T,M>::get() const
00389 {
00390 m.lock();
00391 const T tval = val;
00392 m.unlock();
00393 return tval;
00394 }
00395
00396 template <class T, class M>
00397 SafeVariable<T,M>&
00398 SafeVariable<T,M>::operator=(const T& n)
00399 {
00400 set(n);
00401 return *this;
00402 }
00403
00404 template <class T, class M>
00405 SafeVariable<T,M>::operator const T() const
00406 {
00407 return get();
00408 }
00409
00410
00411
00412
00413
00414
00415 template <>
00416 class ThreadSpecificData<void>
00417 {
00418 public:
00419 class Implementation;
00420 explicit ThreadSpecificData(void (*dst)(void*) = 0);
00421 virtual ~ThreadSpecificData() = 0;
00422 void* set(const void* t);
00423 void* get() const;
00424 private:
00425 Implementation* m_impl;
00426 };
00427
00428 template <class T>
00429 class ThreadSpecificData
00430 : private ThreadSpecificData<void>
00431 {
00432 public:
00433 explicit ThreadSpecificData(const T* p = 0);
00434 ThreadSpecificData (const T* p, void (*TSD_DESTROY)(void*));
00435 virtual ~ThreadSpecificData();
00436 T* set(const T* t);
00437 T* get() const;
00438 T* operator->();
00439 T& operator*();
00440 T* release();
00441 void reset(const T* p = 0);
00442 private:
00443 ThreadSpecificData(const ThreadSpecificData&);
00444 void operator=(const ThreadSpecificData&);
00445 static void tsd_destroy(void*);
00446 };
00447
00448 template <class T>
00449 ThreadSpecificData<T>::ThreadSpecificData(const T* p)
00450 : ThreadSpecificData<void>(tsd_destroy)
00451 {
00452 if ( p ) set(p);
00453 }
00454
00455 template <class T>
00456 ThreadSpecificData<T>::ThreadSpecificData(const T* p, void (*THR_DESTROY)(void*))
00457 : ThreadSpecificData<void>(THR_DESTROY)
00458 {
00459 if ( p ) set(p);
00460 }
00461
00462 template <class T>
00463 ThreadSpecificData<T>::~ThreadSpecificData()
00464 {
00465 reset();
00466 }
00467
00468 template <class T>
00469 T*
00470 ThreadSpecificData<T>::set(const T* v)
00471 {
00472 return static_cast<T*>(ThreadSpecificData<void>::set(static_cast<const void*>(v)));
00473 }
00474
00475 template <class T>
00476 T*
00477 ThreadSpecificData<T>::get() const
00478 {
00479 return static_cast<T*>(ThreadSpecificData<void>::get());
00480 }
00481
00482 template <class T>
00483 T*
00484 ThreadSpecificData<T>::operator->()
00485 {
00486 return get();
00487 }
00488
00489 template <class T>
00490 T&
00491 ThreadSpecificData<T>::operator*()
00492 {
00493 return *get();
00494 }
00495
00496 template <class T>
00497 T*
00498 ThreadSpecificData<T>::release()
00499 {
00500 return set(0);
00501 }
00502
00503 template <class T>
00504 void
00505 ThreadSpecificData<T>::reset(const T* p)
00506 {
00507 delete set(p);
00508 }
00509
00510 template <class T>
00511 void
00512 ThreadSpecificData<T>::tsd_destroy(void* v)
00513 {
00514
00515 delete static_cast<T*>(v);
00516 }
00517
00518
00519
00520
00521
00522 namespace Thread
00523 {
00524 void sleep (const BoxLib::Time& tspec);
00525 int max_threads ();
00526 void exit (void* status = 0);
00527 void yield ();
00528 int getID ();
00529 bool baseThread ();
00530 enum CancelState { Enable, Disable };
00531 CancelState setCancelState (CancelState state);
00532 }
00533
00534
00535
00536 class FunctionThread
00537 {
00538 public:
00539 enum DetachState { Joinable, Detached };
00540 class Implementation;
00541 FunctionThread(Thread_Function func_,
00542 void* arg_ = 0,
00543 DetachState = Joinable,
00544 int stacksize = 0);
00545 ~FunctionThread();
00546 void* join() const;
00547 void detach() const;
00548 protected:
00549 Implementation* m_impl;
00550 };
00551
00552 namespace BoxLib
00553 {
00554 void Thread_Error(const char* file, int lineno, const char* message, int status);
00555 }
00556
00557
00558 #if defined(BL_OLD_STL)
00559 #include <stdlib.h>
00560 #else
00561 #include <cstdlib>
00562 #endif
00563
00564
00565
00566 namespace Thread
00567 {
00568 inline int max_threads() { return 1;}
00569 inline int getID () { return 0; }
00570 inline bool baseThread () { return true; }
00571 }
00572
00573
00574 inline Mutex::Mutex() {}
00575 inline Mutex::~Mutex() {}
00576 inline void Mutex::lock() {}
00577 inline void Mutex::unlock() {}
00578
00579
00580 inline ConditionVariable::ConditionVariable() {}
00581 inline ConditionVariable::~ConditionVariable() {}
00582 inline void ConditionVariable::broadcast() {}
00583 inline void ConditionVariable::signal() {}
00584 inline void ConditionVariable::wait() {}
00585 inline void ConditionVariable::lock() {}
00586 inline void ConditionVariable::unlock() {}
00587
00588 #endif