Scopira 20080306

thread_qtthreads.h

00001 
00002 /*
00003  *  Copyright (c) 2009    National Research Council
00004  *
00005  *  All rights reserved.
00006  *
00007  *  This material is confidential and proprietary information of
00008  *  National Research Council Canada ("Confidential Information").
00009  *  This Confidential Information may only be used and reproduced
00010  *  in accordance with the terms of the license agreement.
00011  *
00012  */
00013 
00014 #ifndef __INCLUDED_SCOPIRA_TOOL_THREAD_PTHREADS_H__
00015 #define __INCLUDED_SCOPIRA_TOOL_THREAD_PTHREADS_H__
00016 
00017 #include <QThread>
00018 #include <QReadWriteLock>
00019 #include <QWaitCondition>
00020 
00021 #include <scopira/tool/platform.h>
00022 #include <scopira/tool/export.h>
00023 
00024 #include <scopira/tool/object.h>
00025 
00026 
00027 namespace scopira
00028 {
00029   namespace tool
00030   {
00031     class runnable_i;
00032     class job_i;
00033 
00036     typedef void* (*runfunc_t)(void*);
00037     class thread;
00038 
00039     class condition;
00040 
00041     class rwlock;
00042     class read_locker;
00043     class write_locker;
00044 
00051     SCOPIRA_EXPORT int num_system_cpus(void);
00052 
00053     template <class T> class shared_area;
00054     template <class T> class event_area;
00055     template <class T> class rw_area;
00056 
00057     template <class T> class area_ptr;
00058     template <class T> class const_area_ptr;
00059     template <class T> class locker_ptr;
00060     template <class T> class event_ptr;
00061     template <class T> class read_locker_ptr;
00062     template <class T> class write_locker_ptr;
00063   }
00064 }
00065 
00071 class scopira::tool::runnable_i
00072 {
00073   public:
00078     SCOPIRA_EXPORT virtual void run(void) = 0;
00079 
00080   protected:
00081     virtual ~runnable_i() { }
00082 };
00083 
00089 class scopira::tool::job_i : public virtual scopira::tool::object
00090 {
00091   public:
00093     SCOPIRA_EXPORT virtual void start(void) = 0;
00094 
00096     SCOPIRA_EXPORT virtual void notify_stop(void) = 0;
00097 
00099     SCOPIRA_EXPORT virtual void wait_stop(void) = 0;
00100 
00102     SCOPIRA_EXPORT virtual bool is_running(void) const = 0;
00103 };
00104 
00110 class scopira::tool::thread : public virtual scopira::tool::job_i,
00111   public virtual scopira::tool::runnable_i
00112 {
00113   public:
00114     typedef int tlskey_t;
00115 
00116   protected:
00117     runnable_i *dm_target;
00118     runfunc_t dm_runfunc;
00119     void *dm_runfunc_arg;
00120 
00121     class myQThread : public QThread
00122     {
00123       public:
00124         myQThread(scopira::tool::thread *parent) : dm_parent(parent) { }
00125       protected:
00126         virtual void run(void) { dm_parent->run(); }
00127       private:
00128         scopira::tool::thread *dm_parent;
00129     } dm_thread;
00130 
00131   public:
00144     SCOPIRA_EXPORT thread(runnable_i* target);
00155     SCOPIRA_EXPORT thread(runfunc_t func, void *arg);
00156 
00158     SCOPIRA_EXPORT virtual ~thread();
00159 
00161     SCOPIRA_EXPORT virtual void run(void);
00162 
00164     SCOPIRA_EXPORT virtual void start(void);
00167     SCOPIRA_EXPORT virtual void notify_stop(void);
00169     SCOPIRA_EXPORT virtual void wait_stop(void);
00171     SCOPIRA_EXPORT virtual bool is_running(void) const { return dm_thread.isRunning(); }
00172 
00179     SCOPIRA_EXPORT static void sleep(int msec);
00180 
00190     SCOPIRA_EXPORT static void open_tls(tlskey_t &outkey);
00196     SCOPIRA_EXPORT static void close_tls(tlskey_t k);
00197 
00205     SCOPIRA_EXPORT static void set_tls(tlskey_t k, void *val);
00213     SCOPIRA_EXPORT static void * get_tls(tlskey_t k);
00214 };
00215 
00226 class scopira::tool::condition
00227 {
00228   protected:
00229     QWaitCondition dm_con;
00230 
00231   public:
00235     SCOPIRA_EXPORT condition(void);
00237     SCOPIRA_EXPORT ~condition();
00238 
00244     SCOPIRA_EXPORT void notify(void);
00250     SCOPIRA_EXPORT void notify_all(void);
00259     SCOPIRA_EXPORT void wait(mutex &mut);
00271     SCOPIRA_EXPORT bool wait(mutex &mut, int msec);
00272 };
00273 
00279 class scopira::tool::rwlock
00280 {
00281   private:
00282     QReadWriteLock dm_rw;
00283 
00284   public:
00286     SCOPIRA_EXPORT rwlock(void);
00288     SCOPIRA_EXPORT ~rwlock();
00289 
00291     SCOPIRA_EXPORT void write_lock(void);
00293     SCOPIRA_EXPORT bool try_write_lock(void);
00295     SCOPIRA_EXPORT void read_lock(void);
00297     SCOPIRA_EXPORT bool try_read_lock(void);
00299     SCOPIRA_EXPORT void unlock(void);
00300 };
00301 
00307 class scopira::tool::read_locker
00308 {
00309   private:
00310     scopira::tool::rwlock &dm_rw;
00311   public:
00313     read_locker(rwlock &rw) : dm_rw(rw) { dm_rw.read_lock(); }
00315     ~read_locker() { dm_rw.unlock(); }
00316 };
00317 
00323 class scopira::tool::write_locker
00324 {
00325   private:
00326     scopira::tool::rwlock &dm_rw;
00327 
00328   public:
00330     write_locker(rwlock &rw) : dm_rw(rw) { dm_rw.write_lock(); }
00332     ~write_locker() { dm_rw.unlock(); }
00333 };
00334 
00342 template <class T> class scopira::tool::shared_area
00343 {
00344   public:
00345     volatile T pm_data; 
00346     mutable scopira::tool::mutex      pm_mutex;
00347 };
00348 
00355 template <class T> class scopira::tool::event_area : public scopira::tool::shared_area<T>
00356 {
00357   public:
00358     mutable scopira::tool::condition  pm_condition;
00359 };
00360 
00367 template <class T> class scopira::tool::rw_area
00368 {
00369   public:
00370     volatile T pm_data; 
00371     mutable scopira::tool::rwlock      pm_rwlock;
00372 };
00373 
00387 template <class T> class scopira::tool::area_ptr
00388 {
00389   protected:
00390     T* dm_ptr;
00391 
00392   public:
00397     area_ptr(const shared_area<T>& ref) : dm_ptr(const_cast<T*>(&ref.pm_data)) { }
00402     area_ptr(const rw_area<T>& ref) : dm_ptr(const_cast<T*>(&ref.pm_data)) { }
00403 
00404   protected:
00409     area_ptr(const volatile T& ref) : dm_ptr(const_cast<T*>(&ref)) { }
00410 
00411   public:
00413     T* get(void) { return dm_ptr; }
00415     T& operator*(void) { return *dm_ptr; }
00417     T* operator->(void) { return dm_ptr; }
00418 
00425     void reset(void) { dm_ptr = const_cast<T*>(const_cast<volatile T*>(dm_ptr)); }  // this is whacky :)
00426 };
00427 
00440 template <class T> class scopira::tool::const_area_ptr
00441 {
00442   protected:
00443     const T* dm_ptr;
00444 
00445   public:
00450     const_area_ptr(const shared_area<T>& ref) : dm_ptr(const_cast<const T*>(&ref.pm_data)) { }
00455     const_area_ptr(const rw_area<T>& ref) : dm_ptr(const_cast<const T*>(&ref.pm_data)) { }
00456 
00457   protected:
00462     const_area_ptr(const volatile T& ref) : dm_ptr(const_cast<T*>(&ref)) { }
00463 
00464   public:
00466     const T* get(void) { return dm_ptr; }
00468     const T& operator*(void) { return *dm_ptr; }
00470     const T* operator->(void) { return dm_ptr; }
00471 
00478     void reset(void) { dm_ptr = const_cast<const T*>(const_cast<volatile T*>(dm_ptr)); }  // this is whacky :)
00479 };
00480 
00489 template <class T> class scopira::tool::locker_ptr : public scopira::tool::area_ptr<T>
00490 {
00491   protected:
00492     scopira::tool::mutex & dm_mut;
00493 
00494   public:
00496     locker_ptr(const shared_area<T>& ref) : area_ptr<T>(ref.pm_data), dm_mut(ref.pm_mutex) { dm_mut.lock(); }
00497 
00499     ~locker_ptr() { dm_mut.unlock(); }
00500   private:
00501 };
00502 
00508 template <class T> class scopira::tool::event_ptr : public scopira::tool::locker_ptr<T>
00509 {
00510   protected:
00511     scopira::tool::condition & dm_cond;
00512 
00513   public:
00515     event_ptr(const event_area<T>& ref) : locker_ptr<T>(ref), dm_cond(ref.pm_condition) { }
00516 
00524     void notify(void) { dm_cond.notify(); }
00532     void notify_all(void) { dm_cond.notify_all(); }
00541     void wait(void) { dm_cond.wait(locker_ptr<T>::dm_mut); }
00551     bool wait(int msec) { return dm_cond.wait(locker_ptr<T>::dm_mut, msec); }
00552 };
00553 
00559 template <class T> class scopira::tool::read_locker_ptr : public scopira::tool::const_area_ptr<T>
00560 {
00561   protected:
00562     scopira::tool::rwlock & dm_rw;
00563 
00564   public:
00566     read_locker_ptr(const rw_area<T>& ref) : const_area_ptr<T>(ref.pm_data), dm_rw(ref.pm_rwlock) { dm_rw.read_lock(); }
00567 
00569     ~read_locker_ptr() { dm_rw.unlock(); }
00570 };
00571 
00577 template <class T> class scopira::tool::write_locker_ptr : public scopira::tool::area_ptr<T>
00578 {
00579   protected:
00580     scopira::tool::rwlock & dm_rw;
00581 
00582   public:
00584     write_locker_ptr(const rw_area<T>& ref) : area_ptr<T>(ref.pm_data), dm_rw(ref.pm_rwlock) { dm_rw.write_lock(); }
00585 
00587     ~write_locker_ptr() { dm_rw.unlock(); }
00588 };
00589 
00590 #endif
00591 
00592