Panda3D
Loading...
Searching...
No Matches
threadWin32Impl.cxx
Go to the documentation of this file.
1/**
2 * PANDA 3D SOFTWARE
3 * Copyright (c) Carnegie Mellon University. All rights reserved.
4 *
5 * All use of this software is subject to the terms of the revised BSD
6 * license. You should have received a copy of this license along
7 * with this source code in a file named "LICENSE."
8 *
9 * @file threadWin32Impl.cxx
10 * @author drose
11 * @date 2006-02-07
12 */
13
14#include "threadWin32Impl.h"
15#include "selectThreadImpl.h"
16
17#ifdef THREAD_WIN32_IMPL
18
19#include "thread.h"
20#include "pointerTo.h"
21#include "config_pipeline.h"
22
23DWORD ThreadWin32Impl::_pt_ptr_index = 0;
24bool ThreadWin32Impl::_got_pt_ptr_index = false;
25
26/**
27 *
28 */
29ThreadWin32Impl::
30~ThreadWin32Impl() {
31 if (thread_cat->is_debug()) {
32 thread_cat.debug() << "Deleting thread " << _parent_obj->get_name() << "\n";
33 }
34
35 CloseHandle(_thread);
36}
37
38/**
39 * Called for the main thread only, which has been already started, to fill in
40 * the values appropriate to that thread.
41 */
42void ThreadWin32Impl::
43setup_main_thread() {
44 _status = S_running;
45}
46
47/**
48 *
49 */
50bool ThreadWin32Impl::
51start(ThreadPriority priority, bool joinable) {
52 _mutex.lock();
53 if (thread_cat->is_debug()) {
54 thread_cat.debug() << "Starting " << *_parent_obj << "\n";
55 }
56
57 nassertd(_status == S_new && _thread == 0) {
58 _mutex.unlock();
59 return false;
60 }
61
62 _joinable = joinable;
63 _status = S_start_called;
64
65 if (!_got_pt_ptr_index) {
66 init_pt_ptr_index();
67 }
68
69 // Increment the parent object's reference count first. The thread will
70 // eventually decrement it when it terminates.
71 _parent_obj->ref();
72 _thread =
73 CreateThread(nullptr, 0, &root_func, (void *)this, 0, &_thread_id);
74
75 if (_thread_id == 0) {
76 // Oops, we couldn't start the thread. Be sure to decrement the reference
77 // count we incremented above, and return false to indicate failure.
78 unref_delete(_parent_obj);
79 _mutex.unlock();
80 return false;
81 }
82
83 // Thread was successfully started. Set the priority as specified.
84 switch (priority) {
85 case TP_low:
86 SetThreadPriority(_thread, THREAD_PRIORITY_BELOW_NORMAL);
87 break;
88
89 case TP_high:
90 SetThreadPriority(_thread, THREAD_PRIORITY_ABOVE_NORMAL);
91 break;
92
93 case TP_urgent:
94 SetThreadPriority(_thread, THREAD_PRIORITY_HIGHEST);
95 break;
96
97 case TP_normal:
98 default:
99 SetThreadPriority(_thread, THREAD_PRIORITY_NORMAL);
100 break;
101 }
102
103 _mutex.unlock();
104 return true;
105}
106
107/**
108 * Blocks the calling process until the thread terminates. If the thread has
109 * already terminated, this returns immediately.
110 */
111void ThreadWin32Impl::
112join() {
113 _mutex.lock();
114 nassertd(_joinable && _status != S_new) {
115 _mutex.unlock();
116 return;
117 }
118
119 while (_status != S_finished) {
120 _cv.wait();
121 }
122 _mutex.unlock();
123}
124
125/**
126 *
127 */
128std::string ThreadWin32Impl::
129get_unique_id() const {
130 std::ostringstream strm;
131 strm << GetCurrentProcessId() << "." << _thread_id;
132
133 return strm.str();
134}
135
136/**
137 * The entry point of each thread.
138 */
139DWORD ThreadWin32Impl::
140root_func(LPVOID data) {
141 TAU_REGISTER_THREAD();
142 {
143 // TAU_PROFILE("void ThreadWin32Impl::root_func()", " ", TAU_USER);
144
145 ThreadWin32Impl *self = (ThreadWin32Impl *)data;
146 BOOL result = TlsSetValue(_pt_ptr_index, self->_parent_obj);
147 nassertr(result, 1);
148
149 {
150 self->_mutex.lock();
151 nassertd(self->_status == S_start_called) {
152 self->_mutex.unlock();
153 return 1;
154 }
155 self->_status = S_running;
156 self->_cv.notify();
157 self->_mutex.unlock();
158 }
159
160 self->_parent_obj->thread_main();
161
162 if (thread_cat->is_debug()) {
163 thread_cat.debug()
164 << "Terminating thread " << self->_parent_obj->get_name()
165 << ", count = " << self->_parent_obj->get_ref_count() << "\n";
166 }
167
168 {
169 self->_mutex.lock();
170 nassertd(self->_status == S_running) {
171 self->_mutex.unlock();
172 return 1;
173 }
174 self->_status = S_finished;
175 self->_cv.notify();
176 self->_mutex.unlock();
177 }
178
179 // Now drop the parent object reference that we grabbed in start(). This
180 // might delete the parent object, and in turn, delete the ThreadWin32Impl
181 // object.
182 unref_delete(self->_parent_obj);
183 }
184
185 return 0;
186}
187
188/**
189 * Allocate a new index to store the Thread parent pointer as a piece of per-
190 * thread private data.
191 */
192void ThreadWin32Impl::
193init_pt_ptr_index() {
194 nassertv(!_got_pt_ptr_index);
195
196 _pt_ptr_index = TlsAlloc();
197 if (_pt_ptr_index == TLS_OUT_OF_INDEXES) {
198 thread_cat->error()
199 << "Unable to associate Thread pointers with threads.\n";
200 return;
201 }
202
203 _got_pt_ptr_index = true;
204
205 // Assume that we must be in the main thread, since this method must be
206 // called before the first thread is spawned.
207 Thread *main_thread_obj = Thread::get_main_thread();
208 BOOL result = TlsSetValue(_pt_ptr_index, main_thread_obj);
209 nassertv(result);
210}
211
212#endif // THREAD_WIN32_IMPL
A thread; that is, a lightweight process.
Definition thread.h:46
get_main_thread
Returns a pointer to the "main" Thread object–this is the Thread that started the whole process.
Definition thread.h:107
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
void unref_delete(RefCountType *ptr)
This global helper function will unref the given ReferenceCount object, and if the reference count re...
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.