00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
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