Source code

Revision control

Copy as Markdown

Other Tools

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