root/trunk/dep/src/zthread/win32/ThreadOps.cxx @ 2

Revision 2, 4.4 kB (checked in by yumileroy, 17 years ago)

[svn] * Proper SVN structure

Original author: Neo2003
Date: 2008-10-02 16:23:55-05:00

Line 
1/*
2 * Copyright (c) 2005, Eric Crahen
3 *
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:
10 *
11 * The above copyright notice and this permission notice shall be included in all
12 * copies or substantial portions of the Software.
13 *
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.
20 *
21 */
22
23#include "ThreadOps.h"
24#include "zthread/Runnable.h"
25#include <process.h>
26
27namespace ZThread {
28
29const ThreadOps ThreadOps::INVALID(0);
30
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.
35 */
36class YieldOps {
37
38  typedef BOOL (*Yield)(void);
39  Yield _fnYield;
40
41public:
42
43  YieldOps() : _fnYield(NULL) {
44
45    OSVERSIONINFO v;
46    v.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
47
48    if(::GetVersionEx(&v) && (v.dwPlatformId == VER_PLATFORM_WIN32_NT)) {
49   
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");
58
59       // REMIND: possibly need to use _T() macro for these strings
60    }
61
62  }
63
64  bool operator()() {
65 
66    // Attempt to yield using the best function available
67    if(!_fnYield || !_fnYield())
68      ::Sleep(0); 
69
70    return true;
71
72  }
73
74};
75
76bool ThreadOps::join(ThreadOps* ops) {
77
78  assert(ops);
79  assert(ops->_tid != 0);
80  assert(ops->_hThread != NULL);
81 
82  if(::WaitForSingleObjectEx(ops->_hThread, INFINITE, FALSE) != WAIT_OBJECT_0)
83    return false;
84
85  ::CloseHandle(ops->_hThread);
86  ops->_hThread = NULL;
87
88  return true;
89
90}
91
92bool ThreadOps::yield() {
93
94  static YieldOps yielder;
95
96  yielder();
97
98  return true;
99
100}
101
102bool ThreadOps::setPriority(ThreadOps* impl, Priority p) {
103
104  assert(impl);
105 
106#if !defined(ZTHREAD_DISABLE_PRIORITY)
107
108  bool result;
109 
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;
122  }
123
124 
125  result = (::SetThreadPriority(impl->_hThread, n) != THREAD_PRIORITY_ERROR_RETURN);
126  return result;
127
128#else
129
130  return true;
131
132#endif
133
134}
135
136bool ThreadOps::getPriority(ThreadOps* impl, Priority& p) {
137
138  assert(impl);
139  bool result = true;
140 
141#if !defined(ZTHREAD_DISABLE_PRIORITY)
142
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;
156  }
157 
158#endif
159
160  return result;
161
162}
163
164
165bool ThreadOps::spawn(Runnable* task) {
166
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
173
174  return _hThread != NULL;
175
176}
177
178unsigned int __stdcall ThreadOps::_dispatch(void *arg) {
179
180  Runnable* task = reinterpret_cast<Runnable*>(arg);
181  assert(task);
182
183  // Run the task from the correct context
184  task->run();
185
186  // Exit the thread
187#if defined(HAVE_BEGINTHREADEX)
188  ::_endthreadex(0);
189#else
190  ExitThread(0);
191#endif
192
193  return 0;
194 
195}
196
197}
Note: See TracBrowser for help on using the browser.