nsprpub/pr/src/cplus/rcthread.cpp

Fri, 16 Jan 2015 04:50:19 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Fri, 16 Jan 2015 04:50:19 +0100
branch
TOR_BUG_9701
changeset 13
44a2da4a2ab2
permissions
-rwxr-xr-x

Replace accessor implementation with direct member state manipulation, by
request https://trac.torproject.org/projects/tor/ticket/9701#comment:32

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

mercurial