зеркало из 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)]
|
[scriptable, uuid(6be5e380-6886-11d3-9382-00104ba0fd40)]
|
||||||
interface nsIThread : nsISupports
|
interface nsIThread : nsISupports
|
||||||
{
|
{
|
||||||
void Join();
|
// These must all match the values used in prthread.h
|
||||||
void Interrupt();
|
const PRUint32 PRIORITY_LOW = 0;
|
||||||
attribute PRThreadPriority Priority;
|
const PRUint32 PRIORITY_NORMAL = 1;
|
||||||
readonly attribute PRThreadScope Scope;
|
const PRUint32 PRIORITY_HIGH = 2;
|
||||||
readonly attribute PRThreadState State;
|
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();
|
[noscript] PRThread GetPRThread();
|
||||||
void Init(in nsIRunnable aRunnable,
|
|
||||||
in unsigned long aStackSize,
|
void init(in nsIRunnable aRunnable,
|
||||||
|
in PRUint32 aStackSize,
|
||||||
in PRThreadPriority aPriority,
|
in PRThreadPriority aPriority,
|
||||||
in PRThreadScope aScope,
|
in PRThreadScope aScope,
|
||||||
in PRThreadState aState);
|
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++
|
%{C++
|
||||||
// returns the nsIThread for the current thread:
|
// returns the nsIThread for the current thread:
|
||||||
static NS_COM nsresult GetCurrent(nsIThread* *result);
|
static NS_COM nsresult GetCurrent(nsIThread* *result);
|
||||||
|
|
|
@ -49,7 +49,7 @@ PRLogModuleInfo* nsIThreadLog = nsnull;
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
nsThread::nsThread()
|
nsThread::nsThread()
|
||||||
: mThread(nsnull), mDead(PR_FALSE)
|
: mThread(nsnull), mDead(PR_FALSE), mStartLock(nsnull)
|
||||||
{
|
{
|
||||||
NS_INIT_REFCNT();
|
NS_INIT_REFCNT();
|
||||||
|
|
||||||
|
@ -62,10 +62,24 @@ nsThread::nsThread()
|
||||||
nsIThreadLog = PR_NewLogModule("nsIThread");
|
nsIThreadLog = PR_NewLogModule("nsIThread");
|
||||||
}
|
}
|
||||||
#endif /* PR_LOGGING */
|
#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()
|
nsThread::~nsThread()
|
||||||
{
|
{
|
||||||
|
if (mStartLock)
|
||||||
|
PR_DestroyLock(mStartLock);
|
||||||
|
|
||||||
PR_LOG(nsIThreadLog, PR_LOG_DEBUG,
|
PR_LOG(nsIThreadLog, PR_LOG_DEBUG,
|
||||||
("nsIThread %p destroyed\n", this));
|
("nsIThread %p destroyed\n", this));
|
||||||
}
|
}
|
||||||
|
@ -75,6 +89,8 @@ nsThread::Main(void* arg)
|
||||||
{
|
{
|
||||||
nsThread* self = (nsThread*)arg;
|
nsThread* self = (nsThread*)arg;
|
||||||
|
|
||||||
|
self->WaitUntilReadyToStartMain();
|
||||||
|
|
||||||
nsresult rv = NS_OK;
|
nsresult rv = NS_OK;
|
||||||
rv = self->RegisterThreadSelf();
|
rv = self->RegisterThreadSelf();
|
||||||
NS_ASSERTION(rv == NS_OK, "failed to set thread self");
|
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
|
NS_ADDREF_THIS(); // released in nsThread::Exit
|
||||||
if (state == PR_JOINABLE_THREAD)
|
if (state == PR_JOINABLE_THREAD)
|
||||||
NS_ADDREF_THIS(); // released in nsThread::Join
|
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,
|
mThread = PR_CreateThread(PR_USER_THREAD, Main, this,
|
||||||
priority, scope, state, stackSize);
|
priority, scope, state, stackSize);
|
||||||
|
PR_Unlock(mStartLock);
|
||||||
PR_LOG(nsIThreadLog, PR_LOG_DEBUG,
|
PR_LOG(nsIThreadLog, PR_LOG_DEBUG,
|
||||||
("nsIThread %p created\n", this));
|
("nsIThread %p created\n", this));
|
||||||
if (mThread == nsnull)
|
if (mThread == nsnull)
|
||||||
|
@ -221,6 +242,26 @@ nsThread::Init(nsIRunnable* runnable,
|
||||||
return NS_OK;
|
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_COM nsresult
|
||||||
NS_NewThread(nsIThread* *result,
|
NS_NewThread(nsIThread* *result,
|
||||||
nsIRunnable* runnable,
|
nsIRunnable* runnable,
|
||||||
|
@ -279,6 +320,15 @@ nsThread::RegisterThreadSelf()
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
nsThread::WaitUntilReadyToStartMain()
|
||||||
|
{
|
||||||
|
PR_Lock(mStartLock);
|
||||||
|
PR_Unlock(mStartLock);
|
||||||
|
PR_DestroyLock(mStartLock);
|
||||||
|
mStartLock = nsnull;
|
||||||
|
}
|
||||||
|
|
||||||
NS_COM nsresult
|
NS_COM nsresult
|
||||||
nsIThread::GetCurrent(nsIThread* *result)
|
nsIThread::GetCurrent(nsIThread* *result)
|
||||||
{
|
{
|
||||||
|
|
|
@ -56,6 +56,7 @@ public:
|
||||||
|
|
||||||
nsresult RegisterThreadSelf();
|
nsresult RegisterThreadSelf();
|
||||||
void SetPRThread(PRThread* thread) { mThread = thread; }
|
void SetPRThread(PRThread* thread) { mThread = thread; }
|
||||||
|
void WaitUntilReadyToStartMain();
|
||||||
|
|
||||||
static void PR_CALLBACK Main(void* arg);
|
static void PR_CALLBACK Main(void* arg);
|
||||||
static void PR_CALLBACK Exit(void* arg);
|
static void PR_CALLBACK Exit(void* arg);
|
||||||
|
@ -70,6 +71,7 @@ protected:
|
||||||
PRThread* mThread;
|
PRThread* mThread;
|
||||||
nsCOMPtr<nsIRunnable> mRunnable;
|
nsCOMPtr<nsIRunnable> mRunnable;
|
||||||
PRBool mDead;
|
PRBool mDead;
|
||||||
|
PRLock* mStartLock;
|
||||||
};
|
};
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
Загрузка…
Ссылка в новой задаче