fix bug 61369. Race between nsThread Init and Main. Also additions to make the interface more useful to non-C++ code. r=brendan sr=waterson

This commit is contained in:
jband%netscape.com 2000-11-30 05:24:53 +00:00
Родитель 327cb9c8b4
Коммит c7a4242a1a
3 изменённых файлов: 86 добавлений и 8 удалений

Просмотреть файл

@ -53,18 +53,44 @@ interface nsIRunnable;
[scriptable, uuid(6be5e380-6886-11d3-9382-00104ba0fd40)]
interface nsIThread : nsISupports
{
void Join();
void Interrupt();
attribute PRThreadPriority Priority;
readonly attribute PRThreadScope Scope;
readonly attribute PRThreadState State;
// These must all match the values used in prthread.h
const PRUint32 PRIORITY_LOW = 0;
const PRUint32 PRIORITY_NORMAL = 1;
const PRUint32 PRIORITY_HIGH = 2;
const PRUint32 PRIORITY_URGENT = 3;
const PRUint32 SCOPE_LOCAL = 0;
const PRUint32 SCOPE_GLOBAL = 1;
const PRUint32 SCOPE_BOUND = 2;
const PRUint32 STATE_JOINABLE = 0;
const PRUint32 STATE_UNJOINABLE = 1;
void join();
void interrupt();
attribute PRThreadPriority priority;
readonly attribute PRThreadScope scope;
readonly attribute PRThreadState state;
[noscript] PRThread GetPRThread();
void Init(in nsIRunnable aRunnable,
in unsigned long aStackSize,
void init(in nsIRunnable aRunnable,
in PRUint32 aStackSize,
in PRThreadPriority aPriority,
in PRThreadScope aScope,
in PRThreadState aState);
/*
* Get the currently running thread (really a static method sort of thing).
*/
readonly attribute nsIThread currentThread;
/*
* Sleep to at least this many milliseconds (only works on currrent thread).
*/
void sleep(in PRUint32 msec);
%{C++
// returns the nsIThread for the current thread:
static NS_COM nsresult GetCurrent(nsIThread* *result);

Просмотреть файл

@ -49,7 +49,7 @@ PRLogModuleInfo* nsIThreadLog = nsnull;
////////////////////////////////////////////////////////////////////////////////
nsThread::nsThread()
: mThread(nsnull), mDead(PR_FALSE)
: mThread(nsnull), mDead(PR_FALSE), mStartLock(nsnull)
{
NS_INIT_REFCNT();
@ -62,10 +62,24 @@ nsThread::nsThread()
nsIThreadLog = PR_NewLogModule("nsIThread");
}
#endif /* PR_LOGGING */
// enforce matching of constants to enums in prthread.h
NS_ASSERTION(nsIThread::PRIORITY_LOW == PR_PRIORITY_LOW &&
nsIThread::PRIORITY_NORMAL == PRIORITY_NORMAL &&
nsIThread::PRIORITY_HIGH == PRIORITY_HIGH &&
nsIThread::PRIORITY_URGENT == PRIORITY_URGENT &&
nsIThread::SCOPE_LOCAL == PR_LOCAL_THREAD &&
nsIThread::SCOPE_GLOBAL == PR_GLOBAL_THREAD &&
nsIThread::STATE_JOINABLE == PR_JOINABLE_THREAD &&
nsIThread::STATE_UNJOINABLE == PR_UNJOINABLE_THREAD,
"Bad constant in nsIThread!");
}
nsThread::~nsThread()
{
if (mStartLock)
PR_DestroyLock(mStartLock);
PR_LOG(nsIThreadLog, PR_LOG_DEBUG,
("nsIThread %p destroyed\n", this));
}
@ -75,6 +89,8 @@ nsThread::Main(void* arg)
{
nsThread* self = (nsThread*)arg;
self->WaitUntilReadyToStartMain();
nsresult rv = NS_OK;
rv = self->RegisterThreadSelf();
NS_ASSERTION(rv == NS_OK, "failed to set thread self");
@ -212,8 +228,13 @@ nsThread::Init(nsIRunnable* runnable,
NS_ADDREF_THIS(); // released in nsThread::Exit
if (state == PR_JOINABLE_THREAD)
NS_ADDREF_THIS(); // released in nsThread::Join
mStartLock = PR_NewLock();
if (mStartLock == nsnull)
return NS_ERROR_OUT_OF_MEMORY;
PR_Lock(mStartLock);
mThread = PR_CreateThread(PR_USER_THREAD, Main, this,
priority, scope, state, stackSize);
PR_Unlock(mStartLock);
PR_LOG(nsIThreadLog, PR_LOG_DEBUG,
("nsIThread %p created\n", this));
if (mThread == nsnull)
@ -221,6 +242,26 @@ nsThread::Init(nsIRunnable* runnable,
return NS_OK;
}
/* readonly attribute nsIThread currentThread; */
NS_IMETHODIMP
nsThread::GetCurrentThread(nsIThread * *aCurrentThread)
{
return GetIThread(PR_CurrentThread(), aCurrentThread);
}
/* void sleep (in PRUint32 msec); */
NS_IMETHODIMP
nsThread::Sleep(PRUint32 msec)
{
if (PR_CurrentThread() != mThread)
return NS_ERROR_FAILURE;
if (PR_Sleep(PR_MillisecondsToInterval(msec)) != PR_SUCCESS)
return NS_ERROR_FAILURE;
return NS_OK;
}
NS_COM nsresult
NS_NewThread(nsIThread* *result,
nsIRunnable* runnable,
@ -279,6 +320,15 @@ nsThread::RegisterThreadSelf()
return NS_OK;
}
void
nsThread::WaitUntilReadyToStartMain()
{
PR_Lock(mStartLock);
PR_Unlock(mStartLock);
PR_DestroyLock(mStartLock);
mStartLock = nsnull;
}
NS_COM nsresult
nsIThread::GetCurrent(nsIThread* *result)
{

Просмотреть файл

@ -56,6 +56,7 @@ public:
nsresult RegisterThreadSelf();
void SetPRThread(PRThread* thread) { mThread = thread; }
void WaitUntilReadyToStartMain();
static void PR_CALLBACK Main(void* arg);
static void PR_CALLBACK Exit(void* arg);
@ -70,6 +71,7 @@ protected:
PRThread* mThread;
nsCOMPtr<nsIRunnable> mRunnable;
PRBool mDead;
PRLock* mStartLock;
};
////////////////////////////////////////////////////////////////////////////////