зеркало из https://github.com/mozilla/pjs.git
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:
Родитель
327cb9c8b4
Коммит
c7a4242a1a
|
@ -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;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
Загрузка…
Ссылка в новой задаче