Back to index

lightning-sunbird  0.9+nobinonly
rcthread.cpp
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
00002 /* ***** BEGIN LICENSE BLOCK *****
00003  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00004  *
00005  * The contents of this file are subject to the Mozilla Public License Version
00006  * 1.1 (the "License"); you may not use this file except in compliance with
00007  * the License. You may obtain a copy of the License at
00008  * http://www.mozilla.org/MPL/
00009  *
00010  * Software distributed under the License is distributed on an "AS IS" basis,
00011  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00012  * for the specific language governing rights and limitations under the
00013  * License.
00014  *
00015  * The Original Code is the Netscape Portable Runtime (NSPR).
00016  *
00017  * The Initial Developer of the Original Code is
00018  * Netscape Communications Corporation.
00019  * Portions created by the Initial Developer are Copyright (C) 1998-2000
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *
00024  * Alternatively, the contents of this file may be used under the terms of
00025  * either the GNU General Public License Version 2 or later (the "GPL"), or
00026  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00027  * in which case the provisions of the GPL or the LGPL are applicable instead
00028  * of those above. If you wish to allow use of your version of this file only
00029  * under the terms of either the GPL or the LGPL, and not to allow others to
00030  * use your version of this file under the terms of the MPL, indicate your
00031  * decision by deleting the provisions above and replace them with the notice
00032  * and other provisions required by the GPL or the LGPL. If you do not delete
00033  * the provisions above, a recipient may use your version of this file under
00034  * the terms of any one of the MPL, the GPL or the LGPL.
00035  *
00036  * ***** END LICENSE BLOCK ***** */
00037 
00038 /* RCThread.cpp - C++ wrapper on NSPR */
00039 
00040 #include "rcthread.h"
00041 #include "rcinrval.h"
00042 
00043 #include <prmem.h>
00044 #include <prlog.h>
00045 #include <stdio.h>
00046 #include <prinit.h>
00047 
00048 static RCPrimordialThread *primordial = NULL;
00049 
00050 void nas_Root(void *arg)
00051 {
00052     RCThread *him = (RCThread*)arg;
00053     while (RCThread::ex_unstarted == him->execution)
00054         (void)PR_Sleep(PR_INTERVAL_NO_TIMEOUT);  /* wait for Start() */
00055     him->RootFunction();  /* he gets a self reference */
00056     if (PR_UNJOINABLE_THREAD == PR_GetThreadState(him->identity))
00057         delete him;
00058 }  /* nas_Root */
00059 
00060 RCThread::~RCThread() { }
00061 
00062 RCThread::RCThread(): RCBase() { }
00063 
00064 RCThread::RCThread(const RCThread&): RCBase()
00065 {
00066     PR_NOT_REACHED("Cannot call thread copy constructor");
00067 }  /* RCThread::RCThread */
00068 
00069 RCThread::RCThread(
00070     RCThread::Scope scope, RCThread::State join, PRUint32 stackSize):
00071     RCBase()
00072 {
00073     execution = ex_unstarted;
00074     identity = PR_CreateThread(
00075         PR_USER_THREAD, nas_Root, this,
00076         PR_GetThreadPriority(PR_CurrentThread()),
00077         (PRThreadScope)scope, (PRThreadState)join, stackSize);
00078 }  /* RCThread::RCThread */
00079 
00080 void RCThread::operator=(const RCThread&)
00081 {
00082     PR_NOT_REACHED("Cannot call thread assignment operator");
00083 }  /* RCThread::operator= */
00084 
00085 
00086 PRStatus RCThread::Start()
00087 {
00088     PRStatus rv;
00089     /* This is an unsafe check, but not too critical */
00090     if (RCThread::ex_unstarted == execution)
00091     {
00092         execution = RCThread::ex_started;
00093         rv = PR_Interrupt(identity);
00094         PR_ASSERT(PR_SUCCESS == rv);
00095     }
00096     else
00097     {
00098         rv = PR_FAILURE;
00099         PR_SetError(PR_INVALID_STATE_ERROR, 0);
00100     }
00101     return rv;
00102 }  /* RCThread::Start */
00103 
00104 PRStatus RCThread::Join()
00105 {
00106     PRStatus rv;
00107     if (RCThread::ex_unstarted == execution)
00108     {
00109         rv = PR_FAILURE;
00110         PR_SetError(PR_INVALID_STATE_ERROR, 0);
00111     }
00112     else rv = PR_JoinThread(identity);
00113     if (PR_SUCCESS == rv) delete this;
00114     return rv;
00115 }  /* RCThread::Join */
00116 
00117 PRStatus RCThread::Interrupt()
00118 {
00119     PRStatus rv;
00120     if (RCThread::ex_unstarted == execution)
00121     {
00122         rv = PR_FAILURE;
00123         PR_SetError(PR_INVALID_STATE_ERROR, 0);
00124     }
00125     else rv = PR_Interrupt(identity);
00126     return rv;
00127 }  /* RCThread::Interrupt */
00128 
00129 void RCThread::ClearInterrupt() { PR_ClearInterrupt(); }
00130 
00131 void RCThread::SetPriority(RCThread::Priority new_priority)
00132     { PR_SetThreadPriority(identity, (PRThreadPriority)new_priority); }
00133 
00134 PRThread *RCThread::Self()
00135     { return PR_CurrentThread(); }
00136 
00137 RCThread::Scope RCThread::GetScope() const
00138     { return (RCThread::Scope)PR_GetThreadScope(identity); }
00139 
00140 RCThread::State RCThread::GetState() const
00141     { return (RCThread::State)PR_GetThreadState(identity); }
00142 
00143 RCThread::Priority RCThread::GetPriority() const
00144     { return (RCThread::Priority)PR_GetThreadPriority(identity); }
00145     
00146 static void _rc_PDDestructor(RCThreadPrivateData* privateData)
00147 {
00148     PR_ASSERT(NULL != privateData);
00149     privateData->Release();
00150 }
00151 
00152 static PRThreadPrivateDTOR _tpd_dtor = (PRThreadPrivateDTOR)_rc_PDDestructor;
00153 
00154 PRStatus RCThread::NewPrivateIndex(PRUintn* index)
00155     { return PR_NewThreadPrivateIndex(index, _tpd_dtor); }
00156 
00157 PRStatus RCThread::SetPrivateData(PRUintn index)
00158     { return PR_SetThreadPrivate(index, NULL); }
00159 
00160 PRStatus RCThread::SetPrivateData(PRUintn index, RCThreadPrivateData* data)
00161 {
00162     return PR_SetThreadPrivate(index, data);
00163 }
00164 
00165 RCThreadPrivateData* RCThread::GetPrivateData(PRUintn index)
00166     { return (RCThreadPrivateData*)PR_GetThreadPrivate(index); }
00167 
00168 PRStatus RCThread::Sleep(const RCInterval& ticks)
00169     { PRIntervalTime tmo = ticks; return PR_Sleep(tmo); }
00170 
00171 RCPrimordialThread *RCThread::WrapPrimordialThread()
00172 {
00173     /*
00174     ** This needs to take more care in insuring that the thread
00175     ** being wrapped is really the primordial thread. This code
00176     ** is assuming that the caller is the primordial thread, and
00177     ** there's nothing to insure that.
00178     */
00179     if (NULL == primordial)
00180     {
00181         /* it doesn't have to be perfect */
00182         RCPrimordialThread *me = new RCPrimordialThread();
00183         PR_ASSERT(NULL != me);
00184         if (NULL == primordial)
00185         {
00186             primordial = me;
00187             me->execution = RCThread::ex_started;
00188             me->identity = PR_GetCurrentThread();
00189         }
00190         else delete me;  /* somebody beat us to it */
00191     }
00192     return primordial;
00193 }  /* RCThread::WrapPrimordialThread */
00194 
00195 RCPrimordialThread::RCPrimordialThread(): RCThread() { }
00196 
00197 RCPrimordialThread::~RCPrimordialThread() { }
00198 
00199 void RCPrimordialThread::RootFunction()
00200 {
00201     PR_NOT_REACHED("Primordial thread calling root function"); 
00202 }  /* RCPrimordialThread::RootFunction */
00203  
00204 PRStatus RCPrimordialThread::Cleanup() { return PR_Cleanup(); }
00205 
00206 PRStatus RCPrimordialThread::SetVirtualProcessors(PRIntn count)
00207 {
00208     PR_SetConcurrency(count);
00209     return PR_SUCCESS;
00210 }  /* SetVirutalProcessors */
00211 
00212 RCThreadPrivateData::RCThreadPrivateData() { }
00213 
00214 RCThreadPrivateData::RCThreadPrivateData(
00215     const RCThreadPrivateData& him) { }
00216 
00217 RCThreadPrivateData::~RCThreadPrivateData() { }
00218 
00219 /* RCThread.c */
00220