00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "threadNsprImpl.h"
00020 #include "selectThreadImpl.h"
00021
00022 #ifdef THREAD_NSPR_IMPL
00023
00024 #include "pointerTo.h"
00025 #include "config_express.h"
00026 #include "mutexHolder.h"
00027
00028 PRUintn ThreadNsprImpl::_pt_ptr_index = 0;
00029 bool ThreadNsprImpl::_got_pt_ptr_index = false;
00030
00031
00032
00033
00034
00035
00036 ThreadNsprImpl::
00037 ~ThreadNsprImpl() {
00038 if (thread_cat.is_debug()) {
00039 thread_cat.debug() << "Deleting thread " << _parent_obj->get_name() << "\n";
00040 }
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058 if (_thread == (PRThread *)NULL) {
00059
00060
00061
00062 return;
00063 }
00064
00065 PRThread *current_thread = PR_GetCurrentThread();
00066 if (current_thread == _thread) {
00067
00068
00069
00070
00071
00072 if (_joinable) {
00073 thread_cat.warning()
00074 << "thread " << _parent_obj->get_name() << " was never joined.\n";
00075 }
00076 return;
00077 }
00078
00079
00080
00081
00082 join();
00083 }
00084
00085
00086
00087
00088
00089
00090 bool ThreadNsprImpl::
00091 start(ThreadPriority priority, bool global, bool joinable) {
00092 MutexHolder holder(_mutex);
00093 if (thread_cat.is_debug()) {
00094 thread_cat.debug() << "Starting thread " << _parent_obj->get_name() << "\n";
00095 }
00096 nassertr(_thread == (PRThread *)NULL, false);
00097 _joinable = joinable;
00098
00099 if (!_got_pt_ptr_index) {
00100
00101
00102 PRStatus result = PR_NewThreadPrivateIndex(&_pt_ptr_index, NULL);
00103 if (result == PR_SUCCESS) {
00104 _got_pt_ptr_index = true;
00105 } else {
00106 thread_cat.error()
00107 << "Unable to associate Thread pointers with threads.\n";
00108 return false;
00109 }
00110 }
00111
00112 PRThreadPriority nspr_pri;
00113
00114 switch (priority) {
00115 case TP_low:
00116 nspr_pri = PR_PRIORITY_LOW;
00117 break;
00118
00119 case TP_normal:
00120 nspr_pri = PR_PRIORITY_NORMAL;
00121 break;
00122
00123 case TP_high:
00124 nspr_pri = PR_PRIORITY_HIGH;
00125 break;
00126
00127 case TP_urgent:
00128 nspr_pri = PR_PRIORITY_URGENT;
00129 break;
00130
00131 default:
00132 nassertr(false, false);
00133 }
00134
00135 PRThreadScope nspr_scope = (global) ? PR_GLOBAL_THREAD : PR_LOCAL_THREAD;
00136
00137 PRThreadState nspr_state = (_joinable) ? PR_JOINABLE_THREAD : PR_UNJOINABLE_THREAD;
00138
00139
00140
00141 _parent_obj->ref();
00142 _thread =
00143 PR_CreateThread(PR_USER_THREAD, &root_func, (void *)_parent_obj,
00144 nspr_pri, nspr_scope, nspr_state, 0);
00145
00146 if (_thread == (PRThread *)NULL) {
00147
00148
00149
00150 unref_delete(_parent_obj);
00151 return false;
00152 }
00153
00154
00155 return true;
00156 }
00157
00158
00159
00160
00161
00162
00163 void ThreadNsprImpl::
00164 join() {
00165 MutexHolder holder(_mutex);
00166 if (_joinable && _thread != (PRThread *)NULL) {
00167 PR_JoinThread(_thread);
00168 _thread = (PRThread *)NULL;
00169 }
00170 }
00171
00172
00173
00174
00175
00176
00177 void ThreadNsprImpl::
00178 root_func(void *data) {
00179 Thread *parent_obj = (Thread *)data;
00180 PRStatus result = PR_SetThreadPrivate(_pt_ptr_index, parent_obj);
00181 nassertv(result == PR_SUCCESS);
00182 parent_obj->thread_main();
00183
00184 if (thread_cat.is_debug()) {
00185 thread_cat.debug()
00186 << "Terminating thread " << parent_obj->get_name()
00187 << ", count = " << parent_obj->get_ref_count() << "\n";
00188 }
00189
00190
00191
00192
00193 unref_delete(parent_obj);
00194 }
00195
00196 #endif // THREAD_NSPR_IMPL