Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00012 #include "../stdafx.h"
00013 #include "thread.h"
00014 #include <pthread.h>
00015 #include <errno.h>
00016
00020 class ThreadObject_pthread : public ThreadObject {
00021 private:
00022 pthread_t thread;
00023 OTTDThreadFunc proc;
00024 void *param;
00025 bool self_destruct;
00026
00027 public:
00031 ThreadObject_pthread(OTTDThreadFunc proc, void *param, bool self_destruct) :
00032 thread(0),
00033 proc(proc),
00034 param(param),
00035 self_destruct(self_destruct)
00036 {
00037 pthread_create(&this->thread, NULL, &stThreadProc, this);
00038 }
00039
00040 bool Exit()
00041 {
00042 assert(pthread_self() == this->thread);
00043
00044 throw OTTDThreadExitSignal();
00045 }
00046
00047 void Join()
00048 {
00049
00050 assert(pthread_self() != this->thread);
00051 pthread_join(this->thread, NULL);
00052 this->thread = 0;
00053 }
00054 private:
00059 static void *stThreadProc(void *thr)
00060 {
00061 ((ThreadObject_pthread *)thr)->ThreadProc();
00062 pthread_exit(NULL);
00063 }
00064
00069 void ThreadProc()
00070 {
00071
00072 try {
00073 this->proc(this->param);
00074 } catch (OTTDThreadExitSignal) {
00075 } catch (...) {
00076 NOT_REACHED();
00077 }
00078
00079 if (self_destruct) {
00080 pthread_detach(pthread_self());
00081 delete this;
00082 }
00083 }
00084 };
00085
00086 bool ThreadObject::New(OTTDThreadFunc proc, void *param, ThreadObject **thread)
00087 {
00088 ThreadObject *to = new ThreadObject_pthread(proc, param, thread == NULL);
00089 if (thread != NULL) *thread = to;
00090 return true;
00091 }
00092
00096 class ThreadMutex_pthread : public ThreadMutex {
00097 private:
00098 pthread_mutex_t mutex;
00099 pthread_cond_t condition;
00100 pthread_mutexattr_t attr;
00101 pthread_t owner;
00102 uint recursive_count;
00103
00104 public:
00105 ThreadMutex_pthread() : owner(0), recursive_count(0)
00106 {
00107 pthread_mutexattr_init(&this->attr);
00108 pthread_mutexattr_settype(&this->attr, PTHREAD_MUTEX_ERRORCHECK);
00109 pthread_mutex_init(&this->mutex, &this->attr);
00110 pthread_cond_init(&this->condition, NULL);
00111 }
00112
00113 ~ThreadMutex_pthread()
00114 {
00115 int err = pthread_cond_destroy(&this->condition);
00116 assert(err != EBUSY);
00117 err = pthread_mutex_destroy(&this->mutex);
00118 assert(err != EBUSY);
00119 }
00120
00121 bool IsOwnedByCurrentThread() const
00122 {
00123 return this->owner == pthread_self();
00124 }
00125
00126 void BeginCritical(bool allow_recursive = false)
00127 {
00128
00129 if (this->IsOwnedByCurrentThread()) {
00130 if (!allow_recursive) NOT_REACHED();
00131 } else {
00132 int err = pthread_mutex_lock(&this->mutex);
00133 assert(err == 0);
00134 assert(this->recursive_count == 0);
00135 this->owner = pthread_self();
00136 }
00137 this->recursive_count++;
00138 }
00139
00140 void EndCritical(bool allow_recursive = false)
00141 {
00142 assert(this->IsOwnedByCurrentThread());
00143 if (!allow_recursive && this->recursive_count != 1) NOT_REACHED();
00144 this->recursive_count--;
00145 if (this->recursive_count != 0) return;
00146 this->owner = 0;
00147 int err = pthread_mutex_unlock(&this->mutex);
00148 assert(err == 0);
00149 }
00150
00151 void WaitForSignal()
00152 {
00153 uint old_recursive_count = this->recursive_count;
00154 this->recursive_count = 0;
00155 this->owner = 0;
00156 int err = pthread_cond_wait(&this->condition, &this->mutex);
00157 assert(err == 0);
00158 this->owner = pthread_self();
00159 this->recursive_count = old_recursive_count;
00160 }
00161
00162 void SendSignal()
00163 {
00164 int err = pthread_cond_signal(&this->condition);
00165 assert(err == 0);
00166 }
00167 };
00168
00169 ThreadMutex *ThreadMutex::New()
00170 {
00171 return new ThreadMutex_pthread();
00172 }