nsprpub/pr/src/cplus/rcthread.cpp

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/nsprpub/pr/src/cplus/rcthread.cpp	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,188 @@
     1.4 +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public
     1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.8 +
     1.9 +/* RCThread.cpp - C++ wrapper on NSPR */
    1.10 +
    1.11 +#include "rcthread.h"
    1.12 +#include "rcinrval.h"
    1.13 +
    1.14 +#include <prmem.h>
    1.15 +#include <prlog.h>
    1.16 +#include <stdio.h>
    1.17 +#include <prinit.h>
    1.18 +
    1.19 +static RCPrimordialThread *primordial = NULL;
    1.20 +
    1.21 +void nas_Root(void *arg)
    1.22 +{
    1.23 +    RCThread *him = (RCThread*)arg;
    1.24 +    while (RCThread::ex_unstarted == him->execution)
    1.25 +        (void)PR_Sleep(PR_INTERVAL_NO_TIMEOUT);  /* wait for Start() */
    1.26 +    him->RootFunction();  /* he gets a self reference */
    1.27 +    if (PR_UNJOINABLE_THREAD == PR_GetThreadState(him->identity))
    1.28 +        delete him;
    1.29 +}  /* nas_Root */
    1.30 +
    1.31 +RCThread::~RCThread() { }
    1.32 +
    1.33 +RCThread::RCThread(): RCBase() { }
    1.34 +
    1.35 +RCThread::RCThread(const RCThread&): RCBase()
    1.36 +{
    1.37 +    PR_NOT_REACHED("Cannot call thread copy constructor");
    1.38 +}  /* RCThread::RCThread */
    1.39 +
    1.40 +RCThread::RCThread(
    1.41 +    RCThread::Scope scope, RCThread::State join, PRUint32 stackSize):
    1.42 +    RCBase()
    1.43 +{
    1.44 +    execution = ex_unstarted;
    1.45 +    identity = PR_CreateThread(
    1.46 +        PR_USER_THREAD, nas_Root, this,
    1.47 +        PR_GetThreadPriority(PR_GetCurrentThread()),
    1.48 +        (PRThreadScope)scope, (PRThreadState)join, stackSize);
    1.49 +}  /* RCThread::RCThread */
    1.50 +
    1.51 +void RCThread::operator=(const RCThread&)
    1.52 +{
    1.53 +    PR_NOT_REACHED("Cannot call thread assignment operator");
    1.54 +}  /* RCThread::operator= */
    1.55 +
    1.56 +
    1.57 +PRStatus RCThread::Start()
    1.58 +{
    1.59 +    PRStatus rv;
    1.60 +    /* This is an unsafe check, but not too critical */
    1.61 +    if (RCThread::ex_unstarted == execution)
    1.62 +    {
    1.63 +        execution = RCThread::ex_started;
    1.64 +        rv = PR_Interrupt(identity);
    1.65 +        PR_ASSERT(PR_SUCCESS == rv);
    1.66 +    }
    1.67 +    else
    1.68 +    {
    1.69 +        rv = PR_FAILURE;
    1.70 +        PR_SetError(PR_INVALID_STATE_ERROR, 0);
    1.71 +    }
    1.72 +    return rv;
    1.73 +}  /* RCThread::Start */
    1.74 +
    1.75 +PRStatus RCThread::Join()
    1.76 +{
    1.77 +    PRStatus rv;
    1.78 +    if (RCThread::ex_unstarted == execution)
    1.79 +    {
    1.80 +        rv = PR_FAILURE;
    1.81 +        PR_SetError(PR_INVALID_STATE_ERROR, 0);
    1.82 +    }
    1.83 +    else rv = PR_JoinThread(identity);
    1.84 +    if (PR_SUCCESS == rv) delete this;
    1.85 +    return rv;
    1.86 +}  /* RCThread::Join */
    1.87 +
    1.88 +PRStatus RCThread::Interrupt()
    1.89 +{
    1.90 +    PRStatus rv;
    1.91 +    if (RCThread::ex_unstarted == execution)
    1.92 +    {
    1.93 +        rv = PR_FAILURE;
    1.94 +        PR_SetError(PR_INVALID_STATE_ERROR, 0);
    1.95 +    }
    1.96 +    else rv = PR_Interrupt(identity);
    1.97 +    return rv;
    1.98 +}  /* RCThread::Interrupt */
    1.99 +
   1.100 +void RCThread::ClearInterrupt() { PR_ClearInterrupt(); }
   1.101 +
   1.102 +void RCThread::SetPriority(RCThread::Priority new_priority)
   1.103 +    { PR_SetThreadPriority(identity, (PRThreadPriority)new_priority); }
   1.104 +
   1.105 +PRThread *RCThread::Self()
   1.106 +    { return PR_GetCurrentThread(); }
   1.107 +
   1.108 +RCThread::Scope RCThread::GetScope() const
   1.109 +    { return (RCThread::Scope)PR_GetThreadScope(identity); }
   1.110 +
   1.111 +RCThread::State RCThread::GetState() const
   1.112 +    { return (RCThread::State)PR_GetThreadState(identity); }
   1.113 +
   1.114 +RCThread::Priority RCThread::GetPriority() const
   1.115 +    { return (RCThread::Priority)PR_GetThreadPriority(identity); }
   1.116 +    
   1.117 +static void _rc_PDDestructor(RCThreadPrivateData* privateData)
   1.118 +{
   1.119 +    PR_ASSERT(NULL != privateData);
   1.120 +    privateData->Release();
   1.121 +}
   1.122 +
   1.123 +static PRThreadPrivateDTOR _tpd_dtor = (PRThreadPrivateDTOR)_rc_PDDestructor;
   1.124 +
   1.125 +PRStatus RCThread::NewPrivateIndex(PRUintn* index)
   1.126 +    { return PR_NewThreadPrivateIndex(index, _tpd_dtor); }
   1.127 +
   1.128 +PRStatus RCThread::SetPrivateData(PRUintn index)
   1.129 +    { return PR_SetThreadPrivate(index, NULL); }
   1.130 +
   1.131 +PRStatus RCThread::SetPrivateData(PRUintn index, RCThreadPrivateData* data)
   1.132 +{
   1.133 +    return PR_SetThreadPrivate(index, data);
   1.134 +}
   1.135 +
   1.136 +RCThreadPrivateData* RCThread::GetPrivateData(PRUintn index)
   1.137 +    { return (RCThreadPrivateData*)PR_GetThreadPrivate(index); }
   1.138 +
   1.139 +PRStatus RCThread::Sleep(const RCInterval& ticks)
   1.140 +    { PRIntervalTime tmo = ticks; return PR_Sleep(tmo); }
   1.141 +
   1.142 +RCPrimordialThread *RCThread::WrapPrimordialThread()
   1.143 +{
   1.144 +    /*
   1.145 +    ** This needs to take more care in insuring that the thread
   1.146 +    ** being wrapped is really the primordial thread. This code
   1.147 +    ** is assuming that the caller is the primordial thread, and
   1.148 +    ** there's nothing to insure that.
   1.149 +    */
   1.150 +    if (NULL == primordial)
   1.151 +    {
   1.152 +        /* it doesn't have to be perfect */
   1.153 +        RCPrimordialThread *me = new RCPrimordialThread();
   1.154 +        PR_ASSERT(NULL != me);
   1.155 +        if (NULL == primordial)
   1.156 +        {
   1.157 +            primordial = me;
   1.158 +            me->execution = RCThread::ex_started;
   1.159 +            me->identity = PR_GetCurrentThread();
   1.160 +        }
   1.161 +        else delete me;  /* somebody beat us to it */
   1.162 +    }
   1.163 +    return primordial;
   1.164 +}  /* RCThread::WrapPrimordialThread */
   1.165 +
   1.166 +RCPrimordialThread::RCPrimordialThread(): RCThread() { }
   1.167 +
   1.168 +RCPrimordialThread::~RCPrimordialThread() { }
   1.169 +
   1.170 +void RCPrimordialThread::RootFunction()
   1.171 +{
   1.172 +    PR_NOT_REACHED("Primordial thread calling root function"); 
   1.173 +}  /* RCPrimordialThread::RootFunction */
   1.174 + 
   1.175 +PRStatus RCPrimordialThread::Cleanup() { return PR_Cleanup(); }
   1.176 +
   1.177 +PRStatus RCPrimordialThread::SetVirtualProcessors(PRIntn count)
   1.178 +{
   1.179 +    PR_SetConcurrency(count);
   1.180 +    return PR_SUCCESS;
   1.181 +}  /* SetVirutalProcessors */
   1.182 +
   1.183 +RCThreadPrivateData::RCThreadPrivateData() { }
   1.184 +
   1.185 +RCThreadPrivateData::RCThreadPrivateData(
   1.186 +    const RCThreadPrivateData& him) { }
   1.187 +
   1.188 +RCThreadPrivateData::~RCThreadPrivateData() { }
   1.189 +
   1.190 +/* RCThread.c */
   1.191 +

mercurial