# thread_win32.cpp

Go to the documentation of this file.

    00001 /* $Id: thread_win32.cpp 17776 2009-10-15 17:41:06Z rubidium $ */
    00002
    00003 /*
    00004  * This file is part of OpenTTD.
    00005  * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
    00006  * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
    00007  * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
    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   /* virtual */ ~ThreadObject_Win32()
    00048   {
    00049     if (this->thread != NULL) {
    00050       CloseHandle(this->thread);
    00051       this->thread = NULL;
    00052     }
    00053   }
    00054
    00055   /* virtual */ bool Exit()
    00056   {
    00057     assert(GetCurrentThreadId() == this->id);
    00058     /* For now we terminate by throwing an error, gives much cleaner cleanup */
    00059     throw OTTDThreadExitSignal();
    00060   }
    00061
    00062   /* virtual */ void Join()
    00063   {
    00064     /* You cannot join yourself */
    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 /* static */ 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
    00112 public:
    00113   ThreadMutex_Win32()
    00114   {
    00115     InitializeCriticalSection(&this->critical_section);
    00116     this->event = CreateEvent(NULL, FALSE, FALSE, NULL);
    00117   }
    00118
    00119   /* virtual */ ~ThreadMutex_Win32()
    00120   {
    00121     DeleteCriticalSection(&this->critical_section);
    00122     CloseHandle(this->event);
    00123   }
    00124
    00125   /* virtual */ void BeginCritical()
    00126   {
    00127     EnterCriticalSection(&this->critical_section);
    00128   }
    00129
    00130   /* virtual */ void EndCritical()
    00131   {
    00132     LeaveCriticalSection(&this->critical_section);
    00133   }
    00134
    00135   /* virtual */ void WaitForSignal()
    00136   {
    00137     this->EndCritical();
    00138     WaitForSingleObject(this->event, INFINITE);
    00139     this->BeginCritical();
    00140   }
    00141
    00142   /* virtual */ void SendSignal()
    00143   {
    00144     SetEvent(this->event);
    00145   }
    00146 };
    00147
    00148 /* static */ ThreadMutex *ThreadMutex::New()
    00149 {
    00150   return new ThreadMutex_Win32();
    00151 }