Remove SIGTYPE_LAST_NOPBS
[openttd/fttd.git] / src / thread / thread_win32.cpp
blob484cc551370f98f715b14d506a88860b17c7cade
1 /* $Id$ */
3 /*
4 * This file is part of OpenTTD.
5 * 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.
6 * 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.
7 * 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/>.
8 */
10 /** @file thread_win32.cpp Win32 thread implementation of Threads. */
12 #include "../stdafx.h"
13 #include "thread.h"
14 #include "../debug.h"
15 #include "../core/alloc_func.hpp"
16 #include <stdlib.h>
17 #include <windows.h>
18 #include <process.h>
20 /**
21 * Win32 thread version for ThreadObject.
23 class ThreadObject_Win32 : public ThreadObject {
24 private:
25 HANDLE thread; ///< System thread identifier.
26 uint id; ///< Thread identifier.
27 OTTDThreadFunc proc; ///< External thread procedure.
28 void *param; ///< Parameter for the external thread procedure.
29 bool self_destruct; ///< Free ourselves when done?
31 public:
32 /**
33 * Create a win32 thread and start it, calling proc(param).
35 ThreadObject_Win32(OTTDThreadFunc proc, void *param, bool self_destruct) :
36 thread(NULL),
37 id(0),
38 proc(proc),
39 param(param),
40 self_destruct(self_destruct)
42 this->thread = (HANDLE)_beginthreadex(NULL, 0, &stThreadProc, this, CREATE_SUSPENDED, &this->id);
43 if (this->thread == NULL) return;
44 ResumeThread(this->thread);
47 /* virtual */ ~ThreadObject_Win32()
49 if (this->thread != NULL) {
50 CloseHandle(this->thread);
51 this->thread = NULL;
55 /* virtual */ bool Exit()
57 assert(GetCurrentThreadId() == this->id);
58 /* For now we terminate by throwing an error, gives much cleaner cleanup */
59 throw OTTDThreadExitSignal();
62 /* virtual */ void Join()
64 /* You cannot join yourself */
65 assert(GetCurrentThreadId() != this->id);
66 WaitForSingleObject(this->thread, INFINITE);
69 private:
70 /**
71 * On thread creation, this function is called, which calls the real startup
72 * function. This to get back into the correct instance again.
74 static uint CALLBACK stThreadProc(void *thr)
76 ((ThreadObject_Win32 *)thr)->ThreadProc();
77 return 0;
80 /**
81 * A new thread is created, and this function is called. Call the custom
82 * function of the creator of the thread.
84 void ThreadProc()
86 try {
87 this->proc(this->param);
88 } catch (OTTDThreadExitSignal) {
89 } catch (...) {
90 NOT_REACHED();
93 if (self_destruct) delete this;
97 /* static */ bool ThreadObject::New(OTTDThreadFunc proc, void *param, ThreadObject **thread)
99 ThreadObject *to = new ThreadObject_Win32(proc, param, thread == NULL);
100 if (thread != NULL) *thread = to;
101 return true;
105 * Win32 thread version of ThreadMutex.
107 class ThreadMutex_Win32 : public ThreadMutex {
108 private:
109 CRITICAL_SECTION critical_section; ///< The critical section we would enter.
110 HANDLE event; ///< Event for signalling.
111 uint recursive_count; ///< Recursive lock count.
113 public:
114 ThreadMutex_Win32() : recursive_count(0)
116 InitializeCriticalSection(&this->critical_section);
117 this->event = CreateEvent(NULL, FALSE, FALSE, NULL);
120 /* virtual */ ~ThreadMutex_Win32()
122 DeleteCriticalSection(&this->critical_section);
123 CloseHandle(this->event);
126 /* virtual */ void BeginCritical(bool allow_recursive = false)
128 /* windows mutex is recursive by itself */
129 EnterCriticalSection(&this->critical_section);
130 this->recursive_count++;
131 if (!allow_recursive && this->recursive_count != 1) NOT_REACHED();
134 /* virtual */ void EndCritical(bool allow_recursive = false)
136 if (!allow_recursive && this->recursive_count != 1) NOT_REACHED();
137 this->recursive_count--;
138 LeaveCriticalSection(&this->critical_section);
141 /* virtual */ void WaitForSignal()
143 assert(this->recursive_count == 1); // Do we need to call Begin/EndCritical multiple times otherwise?
144 this->EndCritical();
145 WaitForSingleObject(this->event, INFINITE);
146 this->BeginCritical();
149 /* virtual */ void SendSignal()
151 SetEvent(this->event);
155 /* static */ ThreadMutex *ThreadMutex::New()
157 return new ThreadMutex_Win32();