thread.h

00001 /* 
00002    EyeDB Object Database Management System
00003    Copyright (C) 1994-2008 SYSRA
00004    
00005    EyeDB is free software; you can redistribute it and/or
00006    modify it under the terms of the GNU Lesser General Public
00007    License as published by the Free Software Foundation; either
00008    version 2.1 of the License, or (at your option) any later version.
00009    
00010    EyeDB is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY; without even the implied warranty of
00012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013    Lesser General Public License for more details.
00014    
00015    You should have received a copy of the GNU Lesser General Public
00016    License along with this library; if not, write to the Free Software
00017    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA 
00018 */
00019 
00020 /*
00021    Author: Eric Viara <viara@sysra.com>
00022 */
00023 
00024 
00025 #ifndef _EYEDBLIB_THREAD_H
00026 #define _EYEDBLIB_THREAD_H
00027 
00028 #include <pthread.h>
00029 #include <sys/time.h>
00030 
00031 #include <iostream>
00032 
00033 #ifdef ULTRASOL7
00034 #include <ostream>
00035 #endif
00036 
00037 namespace eyedblib {
00038 
00039   class Mutex {
00040 
00041   public:
00042     enum Type {
00043       PROCESS_PRIVATE,
00044       PROCESS_SHARED
00045     };
00046     Mutex(Mutex::Type type, bool lock = false);
00047     Mutex(bool lock = false);
00048 
00049     int init(Mutex::Type type, bool lock = false);
00050     int init(bool lock = false);
00051 
00052     int lock();
00053     int unlock();
00054     bool isLocked() const {return locked;}
00055     bool trylock();
00056 
00057     pthread_mutex_t *get_mutex() {return &mut;}
00058 
00059     ~Mutex();
00060 
00061   private:
00062     Type type;
00063     bool locked;
00064     pthread_mutex_t mut;
00065     pthread_mutex_t *forCondWait() {locked = false; return &mut;}
00066     void condWakeup() {locked = true;}
00067     friend class Condition;
00068   };
00069 
00070   struct ProfileStats {
00071     unsigned long long usec;
00072     unsigned long long min_usec, max_usec;
00073     ProfileStats();
00074     void set(struct timeval &, struct timeval &);
00075     void reset();
00076     static void display_time(std::ostream &os, double usec);
00077     void display(std::ostream &os, unsigned int run_cnt) const;
00078   };
00079 
00080   class Condition {
00081 
00082   public:
00083     enum Type {
00084       PROCESS_PRIVATE,
00085       PROCESS_SHARED
00086     };
00087     Condition(Condition::Type type = PROCESS_PRIVATE);
00088 
00089     int init();
00090     int signal();
00091     int wait();
00092     int reset();
00093 
00094     bool timedWait(unsigned long usec);
00095 
00096     pthread_cond_t *get_condition() {return &cnd;}
00097 
00098     bool isProfiled() const {return profiled;}
00099     void setProfile(bool _profiled) {profiled = _profiled;}
00100     void resetProfile();
00101 
00102     struct Profile {
00103       Condition *cond;
00104       unsigned int wait_cnt;
00105       unsigned int wakeup_cnt;
00106       unsigned int signal_cnt;
00107       struct timeval tpsig;
00108       ProfileStats sigwakeup, nowait, wait;
00109       Profile(Condition *cond);
00110       void reset();
00111     } profile;
00112 
00113     Condition::Profile getProfile() const {return profile;}
00114     ~Condition();
00115 
00116   private:
00117     Type type;
00118     unsigned int cond;
00119     unsigned int wait_cnt;
00120     bool profiled;
00121     Mutex mut;
00122     pthread_cond_t cnd;
00123   };
00124 
00125   class Thread {
00126 
00127   public:
00128     enum Type {
00129       SCOPE_PROCESS,
00130       SCOPE_SYSTEM
00131     };
00132 
00133     Thread(Thread::Type type = SCOPE_SYSTEM,
00134            void (*init)(Thread *, void *) = 0, void *init_arg = 0);
00135     Thread(const char *name, Thread::Type type = SCOPE_SYSTEM,
00136            void (*init)(Thread *, void *) = 0, void *init_arg = 0);
00137     void execute(void *(*fun)(void *), void *input_arg = 0);
00138     void *wait();
00139     void join();
00140 
00141     void onStartExec(void (*_start_exec)(Thread *, void *), void * data = 0) {
00142       start_exec = _start_exec;
00143       start_exec_data = data;
00144     }
00145     void onEndExec(void (*_end_exec)(Thread *, void *), void * data = 0) {
00146       end_exec = _end_exec;
00147       end_exec_data = data;
00148     }
00149 
00150     void *getUserData() {return user_data;}
00151     void *setUserData(void *);
00152 
00153     bool isProfiled() {return profiled;}
00154 
00155     void setProfile(bool _profiled) {
00156       profiled = _profiled;
00157       sync.cnd_start.setProfile(profiled);
00158       sync.cnd_end.setProfile(profiled);
00159     }
00160 
00161     void resetProfile();
00162     const char *getName() const {return name;}
00163 
00164     struct Profile {
00165       Thread *thr;
00166       unsigned int run_cnt;
00167       ProfileStats run, wait;
00168       Profile(Thread *);
00169       void reset();
00170     } profile;
00171 
00172     Thread::Profile getProfile() const {return profile;}
00173     pthread_t get_thread() {return tid;}
00174     int get_pid() {return pid;}
00175     bool isIdle() const {return idle;}
00176 
00177     static Thread *getCallingThread();
00178     static Thread *initCallingThread();
00179 
00180     ~Thread();
00181 
00182   private:
00183     bool idle;
00184     static pthread_key_t self_key;
00185     void (*init)(Thread *, void *);
00186     void *init_arg;
00187     char *name;
00188     static void *run(void *);
00189     struct {
00190       Condition cnd_start, cnd_end;
00191     } sync;
00192     struct Exec {
00193       void *input_arg, *return_arg;
00194       void *(*fun)(void *);
00195       Exec() {
00196         input_arg = 0;
00197         return_arg = 0;
00198         fun = 0;
00199       }
00200     } exec;
00201 
00202     void (*start_exec)(Thread *, void *);
00203     void *start_exec_data;
00204     void (*end_exec)(Thread *, void *);
00205     void *end_exec_data;
00206 
00207     bool profiled;
00208     void *user_data;
00209     pthread_t tid;
00210     int pid;
00211     Thread(const char *, bool);
00212     void init_thr(const char *_name, Type type,
00213                   void (*_init)(Thread *, void *), void *_init_arg);
00214 
00215   public:
00216     class Initializer;
00217     friend class Initializer;
00218     friend std::ostream &operator<<(std::ostream &, const Thread::Profile &);
00219   };
00220 
00221   std::ostream &operator<<(std::ostream &, const Condition::Profile &);
00222   std::ostream &operator<<(std::ostream &, const Thread::Profile &);
00223 
00224   class MutexLocker {
00225 
00226   public:
00227     MutexLocker(Mutex &_mut) : mut(_mut) {mut.lock(); locked = true;}
00228     void lock() {mut.lock(); locked = true;}
00229     void unlock() {locked = false; mut.unlock();}
00230     ~MutexLocker() {if (locked) mut.unlock();}
00231 
00232   private:
00233     Mutex &mut;
00234     bool locked;
00235   };
00236 }
00237 
00238 #endif

Generated on Mon Dec 22 18:16:11 2008 for eyedb by  doxygen 1.5.3