michael@0: /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: /* RCThread.cpp - C++ wrapper on NSPR */ michael@0: michael@0: #include "rcthread.h" michael@0: #include "rcinrval.h" michael@0: michael@0: #include michael@0: #include michael@0: #include michael@0: #include michael@0: michael@0: static RCPrimordialThread *primordial = NULL; michael@0: michael@0: void nas_Root(void *arg) michael@0: { michael@0: RCThread *him = (RCThread*)arg; michael@0: while (RCThread::ex_unstarted == him->execution) michael@0: (void)PR_Sleep(PR_INTERVAL_NO_TIMEOUT); /* wait for Start() */ michael@0: him->RootFunction(); /* he gets a self reference */ michael@0: if (PR_UNJOINABLE_THREAD == PR_GetThreadState(him->identity)) michael@0: delete him; michael@0: } /* nas_Root */ michael@0: michael@0: RCThread::~RCThread() { } michael@0: michael@0: RCThread::RCThread(): RCBase() { } michael@0: michael@0: RCThread::RCThread(const RCThread&): RCBase() michael@0: { michael@0: PR_NOT_REACHED("Cannot call thread copy constructor"); michael@0: } /* RCThread::RCThread */ michael@0: michael@0: RCThread::RCThread( michael@0: RCThread::Scope scope, RCThread::State join, PRUint32 stackSize): michael@0: RCBase() michael@0: { michael@0: execution = ex_unstarted; michael@0: identity = PR_CreateThread( michael@0: PR_USER_THREAD, nas_Root, this, michael@0: PR_GetThreadPriority(PR_GetCurrentThread()), michael@0: (PRThreadScope)scope, (PRThreadState)join, stackSize); michael@0: } /* RCThread::RCThread */ michael@0: michael@0: void RCThread::operator=(const RCThread&) michael@0: { michael@0: PR_NOT_REACHED("Cannot call thread assignment operator"); michael@0: } /* RCThread::operator= */ michael@0: michael@0: michael@0: PRStatus RCThread::Start() michael@0: { michael@0: PRStatus rv; michael@0: /* This is an unsafe check, but not too critical */ michael@0: if (RCThread::ex_unstarted == execution) michael@0: { michael@0: execution = RCThread::ex_started; michael@0: rv = PR_Interrupt(identity); michael@0: PR_ASSERT(PR_SUCCESS == rv); michael@0: } michael@0: else michael@0: { michael@0: rv = PR_FAILURE; michael@0: PR_SetError(PR_INVALID_STATE_ERROR, 0); michael@0: } michael@0: return rv; michael@0: } /* RCThread::Start */ michael@0: michael@0: PRStatus RCThread::Join() michael@0: { michael@0: PRStatus rv; michael@0: if (RCThread::ex_unstarted == execution) michael@0: { michael@0: rv = PR_FAILURE; michael@0: PR_SetError(PR_INVALID_STATE_ERROR, 0); michael@0: } michael@0: else rv = PR_JoinThread(identity); michael@0: if (PR_SUCCESS == rv) delete this; michael@0: return rv; michael@0: } /* RCThread::Join */ michael@0: michael@0: PRStatus RCThread::Interrupt() michael@0: { michael@0: PRStatus rv; michael@0: if (RCThread::ex_unstarted == execution) michael@0: { michael@0: rv = PR_FAILURE; michael@0: PR_SetError(PR_INVALID_STATE_ERROR, 0); michael@0: } michael@0: else rv = PR_Interrupt(identity); michael@0: return rv; michael@0: } /* RCThread::Interrupt */ michael@0: michael@0: void RCThread::ClearInterrupt() { PR_ClearInterrupt(); } michael@0: michael@0: void RCThread::SetPriority(RCThread::Priority new_priority) michael@0: { PR_SetThreadPriority(identity, (PRThreadPriority)new_priority); } michael@0: michael@0: PRThread *RCThread::Self() michael@0: { return PR_GetCurrentThread(); } michael@0: michael@0: RCThread::Scope RCThread::GetScope() const michael@0: { return (RCThread::Scope)PR_GetThreadScope(identity); } michael@0: michael@0: RCThread::State RCThread::GetState() const michael@0: { return (RCThread::State)PR_GetThreadState(identity); } michael@0: michael@0: RCThread::Priority RCThread::GetPriority() const michael@0: { return (RCThread::Priority)PR_GetThreadPriority(identity); } michael@0: michael@0: static void _rc_PDDestructor(RCThreadPrivateData* privateData) michael@0: { michael@0: PR_ASSERT(NULL != privateData); michael@0: privateData->Release(); michael@0: } michael@0: michael@0: static PRThreadPrivateDTOR _tpd_dtor = (PRThreadPrivateDTOR)_rc_PDDestructor; michael@0: michael@0: PRStatus RCThread::NewPrivateIndex(PRUintn* index) michael@0: { return PR_NewThreadPrivateIndex(index, _tpd_dtor); } michael@0: michael@0: PRStatus RCThread::SetPrivateData(PRUintn index) michael@0: { return PR_SetThreadPrivate(index, NULL); } michael@0: michael@0: PRStatus RCThread::SetPrivateData(PRUintn index, RCThreadPrivateData* data) michael@0: { michael@0: return PR_SetThreadPrivate(index, data); michael@0: } michael@0: michael@0: RCThreadPrivateData* RCThread::GetPrivateData(PRUintn index) michael@0: { return (RCThreadPrivateData*)PR_GetThreadPrivate(index); } michael@0: michael@0: PRStatus RCThread::Sleep(const RCInterval& ticks) michael@0: { PRIntervalTime tmo = ticks; return PR_Sleep(tmo); } michael@0: michael@0: RCPrimordialThread *RCThread::WrapPrimordialThread() michael@0: { michael@0: /* michael@0: ** This needs to take more care in insuring that the thread michael@0: ** being wrapped is really the primordial thread. This code michael@0: ** is assuming that the caller is the primordial thread, and michael@0: ** there's nothing to insure that. michael@0: */ michael@0: if (NULL == primordial) michael@0: { michael@0: /* it doesn't have to be perfect */ michael@0: RCPrimordialThread *me = new RCPrimordialThread(); michael@0: PR_ASSERT(NULL != me); michael@0: if (NULL == primordial) michael@0: { michael@0: primordial = me; michael@0: me->execution = RCThread::ex_started; michael@0: me->identity = PR_GetCurrentThread(); michael@0: } michael@0: else delete me; /* somebody beat us to it */ michael@0: } michael@0: return primordial; michael@0: } /* RCThread::WrapPrimordialThread */ michael@0: michael@0: RCPrimordialThread::RCPrimordialThread(): RCThread() { } michael@0: michael@0: RCPrimordialThread::~RCPrimordialThread() { } michael@0: michael@0: void RCPrimordialThread::RootFunction() michael@0: { michael@0: PR_NOT_REACHED("Primordial thread calling root function"); michael@0: } /* RCPrimordialThread::RootFunction */ michael@0: michael@0: PRStatus RCPrimordialThread::Cleanup() { return PR_Cleanup(); } michael@0: michael@0: PRStatus RCPrimordialThread::SetVirtualProcessors(PRIntn count) michael@0: { michael@0: PR_SetConcurrency(count); michael@0: return PR_SUCCESS; michael@0: } /* SetVirutalProcessors */ michael@0: michael@0: RCThreadPrivateData::RCThreadPrivateData() { } michael@0: michael@0: RCThreadPrivateData::RCThreadPrivateData( michael@0: const RCThreadPrivateData& him) { } michael@0: michael@0: RCThreadPrivateData::~RCThreadPrivateData() { } michael@0: michael@0: /* RCThread.c */ michael@0: