Initial Patch of Auction House bot rev. 135
[auctionmangos.git] / dep / src / zthread / win32 / ThreadOps.cxx
blob6e8fb8d3b71ad789f7076d60ebb660cc328d1262
1 /*
2 * Copyright (c) 2005, Eric Crahen
4 * Permission is hereby granted, free of charge, to any person obtaining a copy
5 * of this software and associated documentation files (the "Software"), to deal
6 * in the Software without restriction, including without limitation the rights
7 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 * copies of the Software, and to permit persons to whom the Software is furnished
9 * to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice shall be included in all
12 * copies or substantial portions of the Software.
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
18 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 #include "ThreadOps.h"
24 #include "zthread/Runnable.h"
25 #include <process.h>
27 namespace ZThread {
29 const ThreadOps ThreadOps::INVALID(0);
31 /**
32 * Detect OS at runtime and attempt to locate the SwitchToThread
33 * function, which will assist in making the spin lock implementation
34 * which use ThreadOps::yield() a bit fairer.
36 class YieldOps {
38 typedef BOOL (*Yield)(void);
39 Yield _fnYield;
41 public:
43 YieldOps() : _fnYield(NULL) {
45 OSVERSIONINFO v;
46 v.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
48 if(::GetVersionEx(&v) && (v.dwPlatformId == VER_PLATFORM_WIN32_NT)) {
50 // Uses GetModuleHandle() so the reference count on the dll is
51 // not affected. There is a warning about race conditions involving
52 // this function being called as FreeLibrary() completes; however
53 // nearly all win32 applications load this particular and will keep it
54 // in memory until the process exits.
55 HINSTANCE hInst = ::GetModuleHandle("Kernel32.dll");
56 if(hInst != NULL)
57 _fnYield = (Yield)::GetProcAddress(hInst, "SwitchToThread");
59 // REMIND: possibly need to use _T() macro for these strings
64 bool operator()() {
66 // Attempt to yield using the best function available
67 if(!_fnYield || !_fnYield())
68 ::Sleep(0);
70 return true;
76 bool ThreadOps::join(ThreadOps* ops) {
78 assert(ops);
79 assert(ops->_tid != 0);
80 assert(ops->_hThread != NULL);
82 if(::WaitForSingleObjectEx(ops->_hThread, INFINITE, FALSE) != WAIT_OBJECT_0)
83 return false;
85 ::CloseHandle(ops->_hThread);
86 ops->_hThread = NULL;
88 return true;
92 bool ThreadOps::yield() {
94 static YieldOps yielder;
96 yielder();
98 return true;
102 bool ThreadOps::setPriority(ThreadOps* impl, Priority p) {
104 assert(impl);
106 #if !defined(ZTHREAD_DISABLE_PRIORITY)
108 bool result;
110 // Convert
111 int n;
112 switch(p) {
113 case Low:
114 n = THREAD_PRIORITY_BELOW_NORMAL;
115 break;
116 case High:
117 n = THREAD_PRIORITY_ABOVE_NORMAL;
118 break;
119 case Medium:
120 default:
121 n = THREAD_PRIORITY_NORMAL;
125 result = (::SetThreadPriority(impl->_hThread, n) != THREAD_PRIORITY_ERROR_RETURN);
126 return result;
128 #else
130 return true;
132 #endif
136 bool ThreadOps::getPriority(ThreadOps* impl, Priority& p) {
138 assert(impl);
139 bool result = true;
141 #if !defined(ZTHREAD_DISABLE_PRIORITY)
143 // Convert to one of the PRIORITY values
144 switch(::GetThreadPriority(impl->_hThread)) {
145 case THREAD_PRIORITY_ERROR_RETURN:
146 result = false;
147 case THREAD_PRIORITY_BELOW_NORMAL:
148 p = Low;
149 break;
150 case THREAD_PRIORITY_ABOVE_NORMAL:
151 p = High;
152 break;
153 case THREAD_PRIORITY_NORMAL:
154 default:
155 p = Medium;
158 #endif
160 return result;
165 bool ThreadOps::spawn(Runnable* task) {
167 // Start the thread.
168 #if defined(HAVE_BEGINTHREADEX)
169 _hThread = (HANDLE)::_beginthreadex(0, 0, &_dispatch, task, 0, (unsigned int*)&_tid);
170 #else
171 _hThread = CreateThread(0, 0, (LPTHREAD_START_ROUTINE)&_dispatch, task, 0, (DWORD*)&_tid);
172 #endif
174 return _hThread != NULL;
178 unsigned int __stdcall ThreadOps::_dispatch(void *arg) {
180 Runnable* task = reinterpret_cast<Runnable*>(arg);
181 assert(task);
183 // Run the task from the correct context
184 task->run();
186 // Exit the thread
187 #if defined(HAVE_BEGINTHREADEX)
188 ::_endthreadex(0);
189 #else
190 ExitThread(0);
191 #endif
193 return 0;