Files
@ r9908:994583979bb3
Branch filter:
Location: cpp/openttd-patchpack/source/src/thread_win32.cpp
r9908:994583979bb3
3.6 KiB
text/x-c
(svn r14058) -Fix [FS#2224]: NewGRF callback 23 didn't use the NewGRF compatible text stack (minime)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 | /* $Id$ */
/** @file thread_win32.cpp Win32 thread implementation of Threads. */
#include "stdafx.h"
#include "thread.h"
#include "debug.h"
#include "core/alloc_func.hpp"
#include <stdlib.h>
#include <windows.h>
#include <process.h>
/**
* Win32 thread version for ThreadObject.
*/
class ThreadObject_Win32 : public ThreadObject {
private:
uint m_id_thr;
HANDLE m_h_thr;
OTTDThreadFunc m_proc;
void *m_param;
bool m_attached;
public:
/**
* Create a win32 thread and start it, calling proc(param).
*/
ThreadObject_Win32(OTTDThreadFunc proc, void *param) :
m_id_thr(0),
m_h_thr(NULL),
m_proc(proc),
m_param(param),
m_attached(false)
{
m_h_thr = (HANDLE)_beginthreadex(NULL, 0, &stThreadProc, this, CREATE_SUSPENDED, &m_id_thr);
if (m_h_thr == NULL) return;
ResumeThread(m_h_thr);
}
/**
* Create a win32 thread and attach current thread to it.
*/
ThreadObject_Win32() :
m_id_thr(0),
m_h_thr(NULL),
m_proc(NULL),
m_param(NULL),
m_attached(false)
{
BOOL ret = DuplicateHandle(GetCurrentProcess(), GetCurrentThread(), GetCurrentProcess(), &m_h_thr, 0, FALSE, DUPLICATE_SAME_ACCESS);
if (!ret) return;
m_id_thr = GetCurrentThreadId();
}
/* virtual */ ~ThreadObject_Win32()
{
if (m_h_thr != NULL) {
CloseHandle(m_h_thr);
m_h_thr = NULL;
}
}
/* virtual */ bool IsRunning()
{
if (m_h_thr == NULL) return false;
DWORD exit_code = 0;
if (!GetExitCodeThread(m_h_thr, &exit_code)) return false;
return (exit_code == STILL_ACTIVE);
}
/* virtual */ bool WaitForStop()
{
/* You can't wait on yourself */
assert(!IsCurrent());
/* If the thread is not running, waiting is over */
if (!IsRunning()) return true;
DWORD res = WaitForSingleObject(m_h_thr, INFINITE);
return res == WAIT_OBJECT_0;
}
/* virtual */ bool Exit()
{
/* You can only exit yourself */
assert(IsCurrent());
/* If the thread is not running, we are already closed */
if (!IsRunning()) return false;
/* For now we terminate by throwing an error, gives much cleaner cleanup */
throw 0;
}
/* virtual */ void Join()
{
/* You cannot join yourself */
assert(!IsCurrent());
WaitForSingleObject(m_h_thr, INFINITE);
}
/* virtual */ bool IsCurrent()
{
DWORD id_cur = GetCurrentThreadId();
return id_cur == m_id_thr;
}
/* virtual */ uint GetId()
{
return m_id_thr;
}
private:
/**
* On thread creation, this function is called, which calls the real startup
* function. This to get back into the correct instance again.
*/
static uint CALLBACK stThreadProc(void *thr)
{
((ThreadObject_Win32 *)thr)->ThreadProc();
return 0;
}
/**
* A new thread is created, and this function is called. Call the custom
* function of the creator of the thread.
*/
void ThreadProc()
{
try {
m_proc(m_param);
} catch (...) {
}
}
};
/* static */ ThreadObject *ThreadObject::New(OTTDThreadFunc proc, void *param)
{
return new ThreadObject_Win32(proc, param);
}
/* static */ ThreadObject* ThreadObject::AttachCurrent()
{
return new ThreadObject_Win32();
}
/* static */ uint ThreadObject::CurrentId()
{
return GetCurrentThreadId();
}
/**
* Win32 thread version of ThreadSemaphore.
*/
class ThreadSemaphore_Win32 : public ThreadSemaphore {
private:
HANDLE m_handle;
public:
ThreadSemaphore_Win32()
{
m_handle = ::CreateEvent(NULL, FALSE, FALSE, NULL);
}
/* virtual */ ~ThreadSemaphore_Win32()
{
::CloseHandle(m_handle);
}
/* virtual */ void Set()
{
::SetEvent(m_handle);
}
/* virtual */ void Wait()
{
::WaitForSingleObject(m_handle, INFINITE);
}
};
/* static */ ThreadSemaphore *ThreadSemaphore::New()
{
return new ThreadSemaphore_Win32();
}
|