|
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.h */ |
|
7 |
|
8 #if defined(_RCTHREAD_H) |
|
9 #else |
|
10 #define _RCTHREAD_H |
|
11 |
|
12 #include "rcbase.h" |
|
13 |
|
14 #include <prthread.h> |
|
15 |
|
16 class RCInterval; |
|
17 |
|
18 class PR_IMPLEMENT(RCThreadPrivateData) |
|
19 { |
|
20 public: |
|
21 RCThreadPrivateData(); |
|
22 RCThreadPrivateData(const RCThreadPrivateData&); |
|
23 |
|
24 virtual ~RCThreadPrivateData(); |
|
25 |
|
26 virtual void Release() = 0; |
|
27 |
|
28 }; /* RCThreadPrivateData */ |
|
29 |
|
30 class PR_IMPLEMENT(RCThread): public RCBase |
|
31 { |
|
32 public: |
|
33 |
|
34 typedef enum |
|
35 { |
|
36 local = PR_LOCAL_THREAD, global = PR_GLOBAL_THREAD |
|
37 } Scope; |
|
38 |
|
39 typedef enum |
|
40 { |
|
41 joinable = PR_JOINABLE_THREAD, unjoinable = PR_UNJOINABLE_THREAD |
|
42 } State; |
|
43 |
|
44 typedef enum |
|
45 { |
|
46 first = PR_PRIORITY_FIRST, |
|
47 low = PR_PRIORITY_LOW, |
|
48 normal = PR_PRIORITY_NORMAL, |
|
49 high = PR_PRIORITY_HIGH, |
|
50 urgent = PR_PRIORITY_URGENT, |
|
51 last = PR_PRIORITY_LAST |
|
52 } Priority; |
|
53 |
|
54 /* |
|
55 * Create a new thread, providing scope and joinability state. |
|
56 */ |
|
57 RCThread(Scope scope, State state, PRUint32 stackSize=0); |
|
58 |
|
59 /* |
|
60 * New threads are created in a suspended state. It must be 'started" |
|
61 * before it begins execution in the class' defined 'RootFunction()'. |
|
62 */ |
|
63 virtual PRStatus Start(); |
|
64 |
|
65 /* |
|
66 * If a thread is created joinable, then the thread's object exists |
|
67 * until join is called. The thread that calls join will block until |
|
68 * the target thread returns from it's root function. |
|
69 */ |
|
70 virtual PRStatus Join(); |
|
71 |
|
72 /* |
|
73 * The priority of a newly created thread is the same as the creator. |
|
74 * The priority may be changed either by the new thread itself, by |
|
75 * the creator or any other arbitrary thread. |
|
76 */ |
|
77 virtual void SetPriority(Priority newPriority); |
|
78 |
|
79 |
|
80 /* |
|
81 * Interrupt another thread, causing it to stop what it |
|
82 * is doing and return with a well known error code. |
|
83 */ |
|
84 virtual PRStatus Interrupt(); |
|
85 |
|
86 /* |
|
87 * And in case a thread was interrupted and didn't get a chance |
|
88 * to have the notification delivered, a way to cancel the pending |
|
89 * status. |
|
90 */ |
|
91 static void ClearInterrupt(); |
|
92 |
|
93 /* |
|
94 * Methods to discover the attributes of an existing thread. |
|
95 */ |
|
96 static PRThread *Self(); |
|
97 Scope GetScope() const; |
|
98 State GetState() const; |
|
99 Priority GetPriority() const; |
|
100 |
|
101 /* |
|
102 * Thread private data |
|
103 */ |
|
104 static PRStatus NewPrivateIndex(PRUintn* index); |
|
105 |
|
106 /* |
|
107 * Getting it - if you want to modify, make a copy |
|
108 */ |
|
109 static RCThreadPrivateData* GetPrivateData(PRUintn index); |
|
110 |
|
111 /* |
|
112 * Setting it to <empty> - deletes existing data |
|
113 */ |
|
114 static PRStatus SetPrivateData(PRUintn index); |
|
115 |
|
116 /* |
|
117 * Setting it - runtime will make a copy, freeing old iff necessary |
|
118 */ |
|
119 static PRStatus SetPrivateData(PRUintn index, RCThreadPrivateData* data); |
|
120 |
|
121 /* |
|
122 * Scheduling control |
|
123 */ |
|
124 static PRStatus Sleep(const RCInterval& ticks); |
|
125 |
|
126 friend void nas_Root(void*); |
|
127 friend class RCPrimordialThread; |
|
128 protected: |
|
129 |
|
130 /* |
|
131 * The instantiator of a class must not call the destructor. The base |
|
132 * implementation of Join will, and if the thread is created unjoinable, |
|
133 * then the code that called the RootFunction will call the desctructor. |
|
134 */ |
|
135 virtual ~RCThread(); |
|
136 |
|
137 private: |
|
138 |
|
139 /* |
|
140 * This is where a newly created thread begins execution. Returning |
|
141 * from this function is equivalent to terminating the thread. |
|
142 */ |
|
143 virtual void RootFunction() = 0; |
|
144 |
|
145 PRThread *identity; |
|
146 |
|
147 /* Threads are unstarted until started - pretty startling */ |
|
148 enum {ex_unstarted, ex_started} execution; |
|
149 |
|
150 /* There is no public default constructor or copy constructor */ |
|
151 RCThread(); |
|
152 RCThread(const RCThread&); |
|
153 |
|
154 /* And there is no assignment operator */ |
|
155 void operator=(const RCThread&); |
|
156 |
|
157 public: |
|
158 static RCPrimordialThread *WrapPrimordialThread(); |
|
159 |
|
160 }; |
|
161 |
|
162 /* |
|
163 ** class RCPrimordialThread |
|
164 */ |
|
165 class PR_IMPLEMENT(RCPrimordialThread): public RCThread |
|
166 { |
|
167 public: |
|
168 /* |
|
169 ** The primordial thread can (optionally) wait for all created |
|
170 ** threads to terminate before allowing the process to exit. |
|
171 ** Not calling Cleanup() before returning from main() will cause |
|
172 ** the immediate termination of the entire process, including |
|
173 ** any running threads. |
|
174 */ |
|
175 static PRStatus Cleanup(); |
|
176 |
|
177 /* |
|
178 ** Only the primordial thread is allowed to adjust the number of |
|
179 ** virtual processors of the runtime. It's a lame security thing. |
|
180 */ |
|
181 static PRStatus SetVirtualProcessors(PRIntn count=10); |
|
182 |
|
183 friend class RCThread; |
|
184 private: |
|
185 /* |
|
186 ** None other than the runtime can create of destruct |
|
187 ** a primordial thread. It is fabricated by the runtime |
|
188 ** to wrap the thread that initiated the application. |
|
189 */ |
|
190 RCPrimordialThread(); |
|
191 ~RCPrimordialThread(); |
|
192 void RootFunction(); |
|
193 }; /* RCPrimordialThread */ |
|
194 |
|
195 #endif /* defined(_RCTHREAD_H) */ |