# thread_win32.cpp

Go to the documentation of this file.

    00001 /* $Id: thread_win32.cpp 15159 2009-01-20 03:44:43Z rubidium $ */
    00002
    00005 #include "stdafx.h"
    00006 #include "thread.h"
    00007 #include "debug.h"
    00008 #include "core/alloc_func.hpp"
    00009 #include <stdlib.h>
    00010 #include <windows.h>
    00011 #include <process.h>
    00012
    00016 class ThreadObject_Win32 : public ThreadObject {
    00017 private:
    00018   HANDLE thread;
    00019   uint id;
    00020   OTTDThreadFunc proc;
    00021   void *param;
    00022   bool self_destruct;
    00023
    00024 public:
    00028   ThreadObject_Win32(OTTDThreadFunc proc, void *param, bool self_destruct) :
    00029     thread(NULL),
    00030     id(0),
    00031     proc(proc),
    00032     param(param),
    00033     self_destruct(self_destruct)
    00034   {
    00035     this->thread = (HANDLE)_beginthreadex(NULL, 0, &stThreadProc, this, CREATE_SUSPENDED, &this->id);
    00036     if (this->thread == NULL) return;
    00037     ResumeThread(this->thread);
    00038   }
    00039
    00040   /* virtual */ ~ThreadObject_Win32()
    00041   {
    00042     if (this->thread != NULL) {
    00043       CloseHandle(this->thread);
    00044       this->thread = NULL;
    00045     }
    00046   }
    00047
    00048   /* virtual */ bool Exit()
    00049   {
    00050     assert(GetCurrentThreadId() == this->id);
    00051     /* For now we terminate by throwing an error, gives much cleaner cleanup */
    00052     throw OTTDThreadExitSignal();
    00053   }
    00054
    00055   /* virtual */ void Join()
    00056   {
    00057     /* You cannot join yourself */
    00058     assert(GetCurrentThreadId() != this->id);
    00059     WaitForSingleObject(this->thread, INFINITE);
    00060   }
    00061
    00062 private:
    00067   static uint CALLBACK stThreadProc(void *thr)
    00068   {
    00069     ((ThreadObject_Win32 *)thr)->ThreadProc();
    00070     return 0;
    00071   }
    00072
    00077   void ThreadProc()
    00078   {
    00079     try {
    00080       this->proc(this->param);
    00081     } catch (OTTDThreadExitSignal) {
    00082     } catch (...) {
    00083       NOT_REACHED();
    00084     }
    00085
    00086     if (self_destruct) delete this;
    00087   }
    00088 };
    00089
    00090 /* static */ bool ThreadObject::New(OTTDThreadFunc proc, void *param, ThreadObject **thread)
    00091 {
    00092   ThreadObject *to = new ThreadObject_Win32(proc, param, thread == NULL);
    00093   if (thread != NULL) *thread = to;
    00094   return true;
    00095 }
    00096
    00100 class ThreadMutex_Win32 : public ThreadMutex {
    00101 private:
    00102   CRITICAL_SECTION critical_section;
    00103
    00104 public:
    00105   ThreadMutex_Win32()
    00106   {
    00107     InitializeCriticalSection(&this->critical_section);
    00108   }
    00109
    00110   /* virtual */ ~ThreadMutex_Win32()
    00111   {
    00112     DeleteCriticalSection(&this->critical_section);
    00113   }
    00114
    00115   /* virtual */ void BeginCritical()
    00116   {
    00117     EnterCriticalSection(&this->critical_section);
    00118   }
    00119
    00120   /* virtual */ void EndCritical()
    00121   {
    00122     LeaveCriticalSection(&this->critical_section);
    00123   }
    00124 };
    00125
    00126 /* static */ ThreadMutex *ThreadMutex::New()
    00127 {
    00128   return new ThreadMutex_Win32();
    00129 }