00001
00002
00003 #ifndef __ARC_THREAD_H__
00004 #define __ARC_THREAD_H__
00005
00006 #include <map>
00007
00008 #include <glibmm/thread.h>
00009
00010 namespace Arc {
00011
00012 class SimpleCondition;
00013 class SimpleCounter;
00014
00016
00022
00023
00024
00025
00026 const size_t thread_stacksize = (16 * 1024 * 1024);
00027
00029
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00050
00056 bool CreateThreadFunction(void (*func)(void*), void *arg, SimpleCounter* count = NULL);
00057
00059
00065
00066
00067 class ThreadData;
00068
00070
00073 class ThreadDataItem {
00074 friend class ThreadData;
00075 private:
00076 ThreadDataItem(const ThreadDataItem& it);
00077 protected:
00078 virtual ~ThreadDataItem(void);
00079 public:
00082 ThreadDataItem(void);
00086 ThreadDataItem(std::string& key);
00088 ThreadDataItem(const std::string& key);
00093 void Attach(std::string& key);
00097 void Attach(const std::string& key);
00100 static ThreadDataItem* Get(const std::string& key);
00106 virtual void Dup(void);
00107 };
00108
00110
00111 class SimpleCondition {
00112 private:
00113 Glib::Cond cond_;
00114 Glib::Mutex lock_;
00115 unsigned int flag_;
00116 unsigned int waiting_;
00117 public:
00118 SimpleCondition(void)
00119 : flag_(0), waiting_(0) {}
00120 ~SimpleCondition(void) {
00121
00122 broadcast();
00123 }
00125 void lock(void) {
00126 lock_.lock();
00127 }
00129 void unlock(void) {
00130 lock_.unlock();
00131 }
00133 void signal(void) {
00134 lock_.lock();
00135 flag_ = 1;
00136 cond_.signal();
00137 lock_.unlock();
00138 }
00141 void signal_nonblock(void) {
00142 flag_ = 1;
00143 cond_.signal();
00144 }
00147 void broadcast(void) {
00148 lock_.lock();
00149 flag_ = waiting_?waiting_:1;
00150 cond_.broadcast();
00151 lock_.unlock();
00152 }
00154 void wait(void) {
00155 lock_.lock();
00156 ++waiting_;
00157 while (!flag_) cond_.wait(lock_);
00158 --waiting_;
00159 --flag_;
00160 lock_.unlock();
00161 }
00164 void wait_nonblock(void) {
00165 ++waiting_;
00166 while (!flag_) cond_.wait(lock_);
00167 --waiting_;
00168 --flag_;
00169 }
00171 bool wait(int t) {
00172 lock_.lock();
00173 Glib::TimeVal etime;
00174 etime.assign_current_time();
00175 etime.add_milliseconds(t);
00176 bool res(true);
00177 ++waiting_;
00178 while (!flag_) {
00179 res = cond_.timed_wait(lock_, etime);
00180 if (!res) break;
00181 }
00182 --waiting_;
00183 if(res) --flag_;
00184 lock_.unlock();
00185 return res;
00186 }
00188 void reset(void) {
00189 lock_.lock();
00190 flag_ = 0;
00191 lock_.unlock();
00192 }
00193
00194
00195 void forceReset(void) {
00196 flag_ = 0;
00197 waiting_ = 0;
00198 lock_.unlock();
00199 }
00200 };
00201
00204 class SimpleCounter {
00205 private:
00206 Glib::Cond cond_;
00207 Glib::Mutex lock_;
00208 int count_;
00209 public:
00210 SimpleCounter(void) : count_(0) {}
00211 virtual ~SimpleCounter(void);
00213
00214 virtual int inc(void);
00216
00217 virtual int dec(void);
00219 virtual int get(void) const;
00221
00222 virtual int set(int v);
00224 virtual void wait(void) const;
00226
00227 virtual bool wait(int t) const;
00229
00230 virtual void forceReset(void) {
00231 lock_.unlock();
00232 }
00233 };
00234
00235 class TimedMutex {
00236 private:
00237 Glib::Cond cond_;
00238 Glib::Mutex lock_;
00239 bool locked_;
00240 public:
00241 TimedMutex(void):locked_(false) { };
00242 ~TimedMutex(void) { };
00243 bool lock(int t = -1) {
00244 lock_.lock();
00245 if(t < 0) {
00246 while(locked_) {
00247 cond_.wait(lock_);
00248 };
00249 } else if(t > 0) {
00250 Glib::TimeVal etime;
00251 etime.assign_current_time();
00252 etime.add_milliseconds(t);
00253 while(locked_) {
00254 if(!cond_.timed_wait(lock_, etime)) break;
00255 };
00256 };
00257 bool res = !locked_;
00258 locked_=true;
00259 lock_.unlock();
00260 return res;
00261 };
00262 bool trylock(void) {
00263 return lock(0);
00264 };
00265 bool unlock(void) {
00266 lock_.lock();
00267 bool res = locked_;
00268 if(res) {
00269 locked_ = false;
00270 cond_.signal();
00271 };
00272 lock_.unlock();
00273 return true;
00274 };
00275
00276
00277 void forceReset(void) {
00278 locked_ = false;
00279 lock_.unlock();
00280 }
00281 };
00282
00283 class SharedMutex {
00284 private:
00285 Glib::Cond cond_;
00286 Glib::Mutex lock_;
00287 unsigned int exclusive_;
00288 Glib::Thread* thread_;
00289 typedef std::map<Glib::Thread*,unsigned int> shared_list;
00290 shared_list shared_;
00291 void add_shared_lock(void);
00292 void remove_shared_lock(void);
00293 bool have_shared_lock(void);
00294 inline bool have_exclusive_lock(void) {
00295 if(!exclusive_) return false;
00296 if(thread_ == Glib::Thread::self()) return false;
00297 return true;
00298 };
00299 public:
00300 SharedMutex(void):exclusive_(0),thread_(NULL) { };
00301 ~SharedMutex(void) { };
00302 void lockShared(void);
00303 void unlockShared(void);
00304 bool isLockShared(void) {
00305 return (shared_.size() > 0);
00306 };
00307 void lockExclusive(void);
00308 void unlockExclusive(void);
00309 bool isLockExclusive(void) {
00310 return (exclusive_ > 0);
00311 };
00312
00313
00314 void forceReset(void) {
00315 exclusive_ = 0;
00316 thread_ = NULL;
00317 shared_.clear();
00318 lock_.unlock();
00319 };
00320 };
00321
00323 class ThreadedPointerBase {
00324 private:
00325 Glib::Mutex lock_;
00326 Glib::Cond cond_;
00327 unsigned int cnt_;
00328 void *ptr_;
00329 bool released_;
00330 ThreadedPointerBase(ThreadedPointerBase&) {};
00331 ~ThreadedPointerBase(void);
00332 public:
00333 ThreadedPointerBase(void *p);
00334 ThreadedPointerBase* add(void);
00335 void* rem(void);
00336 void* ptr(void) const { return ptr_; };
00337 void rel(void) { released_ = true; };
00338 unsigned int cnt(void) const { return cnt_; };
00339 void lock(void) { lock_.lock(); };
00340 void unlock(void) { lock_.unlock(); };
00341 void wait(void) { cond_.wait(lock_); };
00342 bool wait(Glib::TimeVal etime) {
00343 return cond_.timed_wait(lock_,etime);
00344 };
00345 };
00346
00348
00352 template<typename T>
00353 class ThreadedPointer {
00354 private:
00355 ThreadedPointerBase *object_;
00356 public:
00357 ThreadedPointer(T *p)
00358 : object_(new ThreadedPointerBase(p)) {}
00359 ThreadedPointer(const ThreadedPointer<T>& p)
00360 : object_(p.object_->add()) {}
00361 ThreadedPointer(void)
00362 : object_(new ThreadedPointerBase(NULL)) {}
00363 ~ThreadedPointer(void) {
00364 delete((T*)(object_->rem()));
00365 }
00366 ThreadedPointer<T>& operator=(T *p) {
00367 if (p != object_->ptr()) {
00368 delete((T*)(object_->rem()));
00369 object_ = new ThreadedPointerBase(p);
00370 }
00371 return *this;
00372 }
00373 ThreadedPointer<T>& operator=(const ThreadedPointer<T>& p) {
00374 if (p.object_->ptr() != object_->ptr()) {
00375 delete((T*)(object_->rem()));
00376 object_ = p.object_->add();
00377 }
00378 return *this;
00379 }
00381 T& operator*(void) const {
00382 return *(T*)(object_->ptr());
00383 }
00385 T* operator->(void) const {
00386 return (T*)(object_->ptr());
00387 }
00389 operator bool(void) const {
00390 return ((object_->ptr()) != NULL);
00391 }
00393 bool operator!(void) const {
00394 return ((object_->ptr()) == NULL);
00395 }
00397 bool operator==(const ThreadedPointer& p) const {
00398 return ((T*)(object_->ptr()) == (T*)(p.object_->ptr()));
00399 }
00401 bool operator!=(const ThreadedPointer& p) const {
00402 return ((T*)(object_->ptr()) != (T*)(p.object_->ptr()));
00403 }
00405 bool operator<(const ThreadedPointer& p) const {
00406 return ((T*)(object_->ptr()) < (T*)(p.object_->ptr()));
00407 }
00409 T* Ptr(void) const {
00410 return (T*)(object_->ptr());
00411 }
00413
00415 T* Release(void) {
00416 T* tmp = (T*)(object_->ptr());
00417 object_->rel();
00418 return tmp;
00419 }
00421 unsigned int Holders(void) {
00422 return object_->cnt();
00423 }
00425
00426 unsigned int WaitOutRange(unsigned int minThr, unsigned int maxThr) {
00427 unsigned int r = 0;
00428 object_->lock();
00429 for(;;) {
00430 r = object_->cnt();
00431 if(r <= minThr) break;
00432 if(r >= maxThr) break;
00433 object_->wait();
00434 };
00435 object_->unlock();
00436 return r;
00437 }
00439
00441 unsigned int WaitOutRange(unsigned int minThr, unsigned int maxThr, int timeout) {
00442 if(timeout < 0) return WaitOutRange(minThr, maxThr);
00443 unsigned int r = 0;
00444 object_->lock();
00445 Glib::TimeVal etime;
00446 etime.assign_current_time();
00447 etime.add_milliseconds(timeout);
00448 for(;;) {
00449 r = object_->cnt();
00450 if(r <= minThr) break;
00451 if(r >= maxThr) break;
00452 if(!object_->wait(etime)) break;
00453 };
00454 object_->unlock();
00455 return r;
00456 }
00458
00459 unsigned int WaitInRange(unsigned int minThr, unsigned int maxThr) {
00460 unsigned int r = 0;
00461 object_->lock();
00462 for(;;) {
00463 r = object_->cnt();
00464 if((r >= minThr) && (r <= maxThr)) break;
00465 object_->wait();
00466 };
00467 object_->unlock();
00468 return r;
00469 }
00471
00473 unsigned int WaitInRange(unsigned int minThr, unsigned int maxThr, int timeout) {
00474 if(timeout < 0) return WaitInRange(minThr, maxThr);
00475 unsigned int r = 0;
00476 object_->lock();
00477 Glib::TimeVal etime;
00478 etime.assign_current_time();
00479 etime.add_milliseconds(timeout);
00480 for(;;) {
00481 r = object_->cnt();
00482 if((r >= minThr) && (r <= maxThr)) break;
00483 if(!object_->wait(etime)) break;
00484 };
00485 object_->unlock();
00486 return r;
00487 }
00488
00489 };
00490
00495 class ThreadRegistry {
00496 private:
00497 int counter_;
00498 bool cancel_;
00499 Glib::Cond cond_;
00500 Glib::Mutex lock_;
00501 public:
00502 ThreadRegistry(void);
00503 ~ThreadRegistry(void);
00505 void RegisterThread(void);
00507 void UnregisterThread(void);
00510 bool WaitOrCancel(int timeout);
00514 bool WaitForExit(int timeout = -1);
00515
00516 void RequestCancel(void);
00517
00518
00519 void forceReset(void) {
00520 counter_ = 0;
00521 cancel_ = false;
00522 lock_.unlock();
00523 }
00524 };
00525
00526 void GlibThreadInitialize(void);
00527
00528
00529 class ThreadInitializer {
00530 public:
00531 ThreadInitializer(void) {
00532 GlibThreadInitialize();
00533 }
00534
00535
00536 void forceReset(void);
00537
00538
00539
00540 void waitExit(void);
00541 };
00542
00543
00544
00545
00546
00547
00548
00549
00550 static ThreadInitializer _local_thread_initializer;
00551
00552 }
00553
00554 #endif