00001
00002 #ifndef _MYTHREAD_H_
00003 #define _MYTHREAD_H_
00004
00005 #include <sched.h>
00006 #include <iostream.h>
00007 #include "semaphore.h"
00008 #include <pthread.h>
00009 #include "misc.h"
00010
00011 #ifndef _THREAD_SAFE
00012 #define _THREAD_SAFE
00013 #endif
00014
00015 typedef void *(*void_t)(void *);
00016
00017 class Thread
00018 {
00019 protected:
00020 virtual void RunMain(void *var = NULL) = 0;
00021 bool run_flag;
00022
00023 private:
00024 Semaphore *lock;
00025 int exit_flag;
00026 pthread_t threadID;
00027 pthread_attr_t attr;
00028 friend void Thread_ThreadRun(Thread *th);
00029
00030 public:
00031 void *vptr;
00032
00033 Thread(Semaphore *sem = NULL, int pri = 10);
00034 void SetSemaphore(Semaphore *sem);
00035 virtual ~Thread() {Kill();};
00036 pthread_t ID() { return threadID; }
00037 bool isExit();
00038 void Exit();
00039 int StartMain(void *var = NULL);
00040 int Kill();
00041 bool isRunning();
00042 void SetPriority(int pri);
00043 Semaphore *Lock();
00044
00045 int Wait();
00046 int Post();
00047 };
00048
00049 inline int Thread::StartMain(void *var)
00050 {
00051 vptr = var;
00052 return pthread_create(&threadID, &attr, void_t(&Thread_ThreadRun), this);
00053 }
00054
00055 inline Thread::Thread(Semaphore *sem, int pri)
00056 {
00057 run_flag = false;
00058 exit_flag = 0;
00059 SetSemaphore(sem);
00060 SetPriority(pri);
00061 }
00062
00063 inline void Thread::SetSemaphore(Semaphore *sem)
00064 {
00065 lock = sem;
00066 }
00067
00068 inline Semaphore *Thread::Lock()
00069 {
00070 return lock;
00071 }
00072
00073 inline bool Thread::isExit()
00074 {
00075 return (exit_flag == 1);
00076 }
00077
00078 inline void Thread::Exit()
00079 {
00080 exit_flag = 1;
00081 if (!run_flag) return;
00082
00083 cout << "Waiting for thread to exit...." << flush;
00084 while (run_flag) { mySleep(1000); }
00085 cout << "done!" << endl << flush;
00086 }
00087
00088 inline int Thread::Kill()
00089 {
00090 if (!run_flag) return 0;
00091
00092 pthread_cancel(threadID);
00093 run_flag = false;
00094
00095 return 1;
00096 }
00097
00098 inline bool Thread::isRunning()
00099 {
00100 return run_flag;
00101 }
00102
00103 inline int Thread::Wait()
00104 {
00105 return lock->Wait();
00106 }
00107
00108 inline int Thread::Post()
00109 {
00110 return lock->Post();
00111 }
00112
00113 inline void Thread::SetPriority(int pri)
00114 {
00115 struct sched_param sched;
00116
00117 pthread_attr_init(&attr);
00118 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
00119
00120 int policy = sched_getscheduler(0);
00121 if (policy < 0)
00122 {
00123 sched_getparam(0, &sched);
00124
00125 pri = sched.sched_priority - pri;
00126 if (pri > sched_get_priority_max(policy))
00127 pri = sched_get_priority_max(policy);
00128
00129 if (pri < sched_get_priority_min(policy))
00130 pri = sched_get_priority_min(policy);
00131
00132 sched.sched_priority = pri;
00133 pthread_attr_setschedpolicy(&attr, policy);
00134 pthread_attr_setschedparam(&attr, &sched);
00135 }
00136 if(!pri)
00137 pthread_attr_setinheritsched(&attr, PTHREAD_INHERIT_SCHED);
00138 }
00139
00140 inline void Thread_ThreadRun(Thread *th)
00141 {
00142 #ifndef __CYGWIN32__
00143 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
00144 pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
00145 #endif
00146 th->run_flag = 1;
00147 th->RunMain(th->vptr);
00148 th->run_flag = 0;
00149 }
00150
00151 #define DEFINE_TEMPLATE_THREAD_CLASS(T, Etype) class T : public Thread {\
00152 private: void Run(Etype *v = NULL); \
00153 void RunMain(void *v = NULL) { Run(reinterpret_cast<Etype*>(v)); } \
00154 public: T(Semaphore *sem = NULL, int pri = 0) : Thread(sem,pri) {}; \
00155 ~T() {Exit();} \
00156 int Start(Etype *v) {return StartMain(reinterpret_cast<void*>(v));} \
00157 }
00158
00159 #define DEFINE_THREAD_CLASS(T) DEFINE_TEMPLATE_THREAD_CLASS(T, void)
00160
00161 #endif // _MYTHREAD_H_
00162