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 "../debug.h"
00015 #include "../core/alloc_func.hpp"
00016 #include <stdlib.h>
00017 #include <windows.h>
00018 #include <process.h>
00019
00023 class ThreadObject_Win32 : public ThreadObject {
00024 private:
00025 HANDLE thread;
00026 uint id;
00027 OTTDThreadFunc proc;
00028 void *param;
00029 bool self_destruct;
00030
00031 public:
00035 ThreadObject_Win32(OTTDThreadFunc proc, void *param, bool self_destruct) :
00036 thread(NULL),
00037 id(0),
00038 proc(proc),
00039 param(param),
00040 self_destruct(self_destruct)
00041 {
00042 this->thread = (HANDLE)_beginthreadex(NULL, 0, &stThreadProc, this, CREATE_SUSPENDED, &this->id);
00043 if (this->thread == NULL) return;
00044 ResumeThread(this->thread);
00045 }
00046
00047 ~ThreadObject_Win32()
00048 {
00049 if (this->thread != NULL) {
00050 CloseHandle(this->thread);
00051 this->thread = NULL;
00052 }
00053 }
00054
00055 bool Exit()
00056 {
00057 assert(GetCurrentThreadId() == this->id);
00058
00059 throw OTTDThreadExitSignal();
00060 }
00061
00062 void Join()
00063 {
00064
00065 assert(GetCurrentThreadId() != this->id);
00066 WaitForSingleObject(this->thread, INFINITE);
00067 }
00068
00069 private:
00074 static uint CALLBACK stThreadProc(void *thr)
00075 {
00076 ((ThreadObject_Win32 *)thr)->ThreadProc();
00077 return 0;
00078 }
00079
00084 void ThreadProc()
00085 {
00086 try {
00087 this->proc(this->param);
00088 } catch (OTTDThreadExitSignal) {
00089 } catch (...) {
00090 NOT_REACHED();
00091 }
00092
00093 if (self_destruct) delete this;
00094 }
00095 };
00096
00097 bool ThreadObject::New(OTTDThreadFunc proc, void *param, ThreadObject **thread)
00098 {
00099 ThreadObject *to = new ThreadObject_Win32(proc, param, thread == NULL);
00100 if (thread != NULL) *thread = to;
00101 return true;
00102 }
00103
00107 class ThreadMutex_Win32 : public ThreadMutex {
00108 private:
00109 CRITICAL_SECTION critical_section;
00110 HANDLE event;
00111 uint recursive_count;
00112
00113 public:
00114 ThreadMutex_Win32() : recursive_count(0)
00115 {
00116 InitializeCriticalSection(&this->critical_section);
00117 this->event = CreateEvent(NULL, FALSE, FALSE, NULL);
00118 }
00119
00120 ~ThreadMutex_Win32()
00121 {
00122 DeleteCriticalSection(&this->critical_section);
00123 CloseHandle(this->event);
00124 }
00125
00126 void BeginCritical(bool allow_recursive = false)
00127 {
00128
00129 EnterCriticalSection(&this->critical_section);
00130 this->recursive_count++;
00131 if (!allow_recursive && this->recursive_count != 1) NOT_REACHED();
00132 }
00133
00134 void EndCritical(bool allow_recursive = false)
00135 {
00136 if (!allow_recursive && this->recursive_count != 1) NOT_REACHED();
00137 this->recursive_count--;
00138 LeaveCriticalSection(&this->critical_section);
00139 }
00140
00141 void WaitForSignal()
00142 {
00143 assert(this->recursive_count == 1);
00144 this->EndCritical();
00145 WaitForSingleObject(this->event, INFINITE);
00146 this->BeginCritical();
00147 }
00148
00149 void SendSignal()
00150 {
00151 SetEvent(this->event);
00152 }
00153 };
00154
00155 ThreadMutex *ThreadMutex::New()
00156 {
00157 return new ThreadMutex_Win32();
00158 }