tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

rcthread.cpp (5446B)


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