Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
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/. */
6 /* RCThread.cpp - C++ wrapper on NSPR */
8 #include "rcthread.h"
9 #include "rcinrval.h"
11 #include <prmem.h>
12 #include <prlog.h>
13 #include <stdio.h>
14 #include <prinit.h>
16 static RCPrimordialThread *primordial = NULL;
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 */
28 RCThread::~RCThread() { }
30 RCThread::RCThread(): RCBase() { }
32 RCThread::RCThread(const RCThread&): RCBase()
33 {
34 PR_NOT_REACHED("Cannot call thread copy constructor");
35 } /* RCThread::RCThread */
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 */
48 void RCThread::operator=(const RCThread&)
49 {
50 PR_NOT_REACHED("Cannot call thread assignment operator");
51 } /* RCThread::operator= */
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 */
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 */
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 */
97 void RCThread::ClearInterrupt() { PR_ClearInterrupt(); }
99 void RCThread::SetPriority(RCThread::Priority new_priority)
100 { PR_SetThreadPriority(identity, (PRThreadPriority)new_priority); }
102 PRThread *RCThread::Self()
103 { return PR_GetCurrentThread(); }
105 RCThread::Scope RCThread::GetScope() const
106 { return (RCThread::Scope)PR_GetThreadScope(identity); }
108 RCThread::State RCThread::GetState() const
109 { return (RCThread::State)PR_GetThreadState(identity); }
111 RCThread::Priority RCThread::GetPriority() const
112 { return (RCThread::Priority)PR_GetThreadPriority(identity); }
114 static void _rc_PDDestructor(RCThreadPrivateData* privateData)
115 {
116 PR_ASSERT(NULL != privateData);
117 privateData->Release();
118 }
120 static PRThreadPrivateDTOR _tpd_dtor = (PRThreadPrivateDTOR)_rc_PDDestructor;
122 PRStatus RCThread::NewPrivateIndex(PRUintn* index)
123 { return PR_NewThreadPrivateIndex(index, _tpd_dtor); }
125 PRStatus RCThread::SetPrivateData(PRUintn index)
126 { return PR_SetThreadPrivate(index, NULL); }
128 PRStatus RCThread::SetPrivateData(PRUintn index, RCThreadPrivateData* data)
129 {
130 return PR_SetThreadPrivate(index, data);
131 }
133 RCThreadPrivateData* RCThread::GetPrivateData(PRUintn index)
134 { return (RCThreadPrivateData*)PR_GetThreadPrivate(index); }
136 PRStatus RCThread::Sleep(const RCInterval& ticks)
137 { PRIntervalTime tmo = ticks; return PR_Sleep(tmo); }
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 */
163 RCPrimordialThread::RCPrimordialThread(): RCThread() { }
165 RCPrimordialThread::~RCPrimordialThread() { }
167 void RCPrimordialThread::RootFunction()
168 {
169 PR_NOT_REACHED("Primordial thread calling root function");
170 } /* RCPrimordialThread::RootFunction */
172 PRStatus RCPrimordialThread::Cleanup() { return PR_Cleanup(); }
174 PRStatus RCPrimordialThread::SetVirtualProcessors(PRIntn count)
175 {
176 PR_SetConcurrency(count);
177 return PR_SUCCESS;
178 } /* SetVirutalProcessors */
180 RCThreadPrivateData::RCThreadPrivateData() { }
182 RCThreadPrivateData::RCThreadPrivateData(
183 const RCThreadPrivateData& him) { }
185 RCThreadPrivateData::~RCThreadPrivateData() { }
187 /* RCThread.c */