|
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
|
2 /* This Source Code Form is subject to the terms of the Mozilla Public |
|
3 * License, v. 2.0. If a copy of the MPL was not distributed with this |
|
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
5 |
|
6 /* RCThread.cpp - C++ wrapper on NSPR */ |
|
7 |
|
8 #include "rcthread.h" |
|
9 #include "rcinrval.h" |
|
10 |
|
11 #include <prmem.h> |
|
12 #include <prlog.h> |
|
13 #include <stdio.h> |
|
14 #include <prinit.h> |
|
15 |
|
16 static RCPrimordialThread *primordial = NULL; |
|
17 |
|
18 void nas_Root(void *arg) |
|
19 { |
|
20 RCThread *him = (RCThread*)arg; |
|
21 while (RCThread::ex_unstarted == him->execution) |
|
22 (void)PR_Sleep(PR_INTERVAL_NO_TIMEOUT); /* wait for Start() */ |
|
23 him->RootFunction(); /* he gets a self reference */ |
|
24 if (PR_UNJOINABLE_THREAD == PR_GetThreadState(him->identity)) |
|
25 delete him; |
|
26 } /* nas_Root */ |
|
27 |
|
28 RCThread::~RCThread() { } |
|
29 |
|
30 RCThread::RCThread(): RCBase() { } |
|
31 |
|
32 RCThread::RCThread(const RCThread&): RCBase() |
|
33 { |
|
34 PR_NOT_REACHED("Cannot call thread copy constructor"); |
|
35 } /* RCThread::RCThread */ |
|
36 |
|
37 RCThread::RCThread( |
|
38 RCThread::Scope scope, RCThread::State join, PRUint32 stackSize): |
|
39 RCBase() |
|
40 { |
|
41 execution = ex_unstarted; |
|
42 identity = PR_CreateThread( |
|
43 PR_USER_THREAD, nas_Root, this, |
|
44 PR_GetThreadPriority(PR_GetCurrentThread()), |
|
45 (PRThreadScope)scope, (PRThreadState)join, stackSize); |
|
46 } /* RCThread::RCThread */ |
|
47 |
|
48 void RCThread::operator=(const RCThread&) |
|
49 { |
|
50 PR_NOT_REACHED("Cannot call thread assignment operator"); |
|
51 } /* RCThread::operator= */ |
|
52 |
|
53 |
|
54 PRStatus RCThread::Start() |
|
55 { |
|
56 PRStatus rv; |
|
57 /* This is an unsafe check, but not too critical */ |
|
58 if (RCThread::ex_unstarted == execution) |
|
59 { |
|
60 execution = RCThread::ex_started; |
|
61 rv = PR_Interrupt(identity); |
|
62 PR_ASSERT(PR_SUCCESS == rv); |
|
63 } |
|
64 else |
|
65 { |
|
66 rv = PR_FAILURE; |
|
67 PR_SetError(PR_INVALID_STATE_ERROR, 0); |
|
68 } |
|
69 return rv; |
|
70 } /* RCThread::Start */ |
|
71 |
|
72 PRStatus RCThread::Join() |
|
73 { |
|
74 PRStatus rv; |
|
75 if (RCThread::ex_unstarted == execution) |
|
76 { |
|
77 rv = PR_FAILURE; |
|
78 PR_SetError(PR_INVALID_STATE_ERROR, 0); |
|
79 } |
|
80 else rv = PR_JoinThread(identity); |
|
81 if (PR_SUCCESS == rv) delete this; |
|
82 return rv; |
|
83 } /* RCThread::Join */ |
|
84 |
|
85 PRStatus RCThread::Interrupt() |
|
86 { |
|
87 PRStatus rv; |
|
88 if (RCThread::ex_unstarted == execution) |
|
89 { |
|
90 rv = PR_FAILURE; |
|
91 PR_SetError(PR_INVALID_STATE_ERROR, 0); |
|
92 } |
|
93 else rv = PR_Interrupt(identity); |
|
94 return rv; |
|
95 } /* RCThread::Interrupt */ |
|
96 |
|
97 void RCThread::ClearInterrupt() { PR_ClearInterrupt(); } |
|
98 |
|
99 void RCThread::SetPriority(RCThread::Priority new_priority) |
|
100 { PR_SetThreadPriority(identity, (PRThreadPriority)new_priority); } |
|
101 |
|
102 PRThread *RCThread::Self() |
|
103 { return PR_GetCurrentThread(); } |
|
104 |
|
105 RCThread::Scope RCThread::GetScope() const |
|
106 { return (RCThread::Scope)PR_GetThreadScope(identity); } |
|
107 |
|
108 RCThread::State RCThread::GetState() const |
|
109 { return (RCThread::State)PR_GetThreadState(identity); } |
|
110 |
|
111 RCThread::Priority RCThread::GetPriority() const |
|
112 { return (RCThread::Priority)PR_GetThreadPriority(identity); } |
|
113 |
|
114 static void _rc_PDDestructor(RCThreadPrivateData* privateData) |
|
115 { |
|
116 PR_ASSERT(NULL != privateData); |
|
117 privateData->Release(); |
|
118 } |
|
119 |
|
120 static PRThreadPrivateDTOR _tpd_dtor = (PRThreadPrivateDTOR)_rc_PDDestructor; |
|
121 |
|
122 PRStatus RCThread::NewPrivateIndex(PRUintn* index) |
|
123 { return PR_NewThreadPrivateIndex(index, _tpd_dtor); } |
|
124 |
|
125 PRStatus RCThread::SetPrivateData(PRUintn index) |
|
126 { return PR_SetThreadPrivate(index, NULL); } |
|
127 |
|
128 PRStatus RCThread::SetPrivateData(PRUintn index, RCThreadPrivateData* data) |
|
129 { |
|
130 return PR_SetThreadPrivate(index, data); |
|
131 } |
|
132 |
|
133 RCThreadPrivateData* RCThread::GetPrivateData(PRUintn index) |
|
134 { return (RCThreadPrivateData*)PR_GetThreadPrivate(index); } |
|
135 |
|
136 PRStatus RCThread::Sleep(const RCInterval& ticks) |
|
137 { PRIntervalTime tmo = ticks; return PR_Sleep(tmo); } |
|
138 |
|
139 RCPrimordialThread *RCThread::WrapPrimordialThread() |
|
140 { |
|
141 /* |
|
142 ** This needs to take more care in insuring that the thread |
|
143 ** being wrapped is really the primordial thread. This code |
|
144 ** is assuming that the caller is the primordial thread, and |
|
145 ** there's nothing to insure that. |
|
146 */ |
|
147 if (NULL == primordial) |
|
148 { |
|
149 /* it doesn't have to be perfect */ |
|
150 RCPrimordialThread *me = new RCPrimordialThread(); |
|
151 PR_ASSERT(NULL != me); |
|
152 if (NULL == primordial) |
|
153 { |
|
154 primordial = me; |
|
155 me->execution = RCThread::ex_started; |
|
156 me->identity = PR_GetCurrentThread(); |
|
157 } |
|
158 else delete me; /* somebody beat us to it */ |
|
159 } |
|
160 return primordial; |
|
161 } /* RCThread::WrapPrimordialThread */ |
|
162 |
|
163 RCPrimordialThread::RCPrimordialThread(): RCThread() { } |
|
164 |
|
165 RCPrimordialThread::~RCPrimordialThread() { } |
|
166 |
|
167 void RCPrimordialThread::RootFunction() |
|
168 { |
|
169 PR_NOT_REACHED("Primordial thread calling root function"); |
|
170 } /* RCPrimordialThread::RootFunction */ |
|
171 |
|
172 PRStatus RCPrimordialThread::Cleanup() { return PR_Cleanup(); } |
|
173 |
|
174 PRStatus RCPrimordialThread::SetVirtualProcessors(PRIntn count) |
|
175 { |
|
176 PR_SetConcurrency(count); |
|
177 return PR_SUCCESS; |
|
178 } /* SetVirutalProcessors */ |
|
179 |
|
180 RCThreadPrivateData::RCThreadPrivateData() { } |
|
181 |
|
182 RCThreadPrivateData::RCThreadPrivateData( |
|
183 const RCThreadPrivateData& him) { } |
|
184 |
|
185 RCThreadPrivateData::~RCThreadPrivateData() { } |
|
186 |
|
187 /* RCThread.c */ |
|
188 |