зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1361164 - Add infallible IsOnCurrentThread to nsIEventTarget (r=froydnj)
MozReview-Commit-ID: 12bk9hQ7Wnv
This commit is contained in:
Родитель
53a717beee
Коммит
5ddda3bb77
|
@ -963,6 +963,12 @@ EventSourceImpl::IsOnCurrentThread(bool* aResult)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP_(bool)
|
||||
EventSourceImpl::IsOnCurrentThreadInfallible()
|
||||
{
|
||||
return IsTargetThread();
|
||||
}
|
||||
|
||||
nsresult
|
||||
EventSourceImpl::GetBaseURI(nsIURI** aBaseURI)
|
||||
{
|
||||
|
|
|
@ -2880,6 +2880,12 @@ WebSocketImpl::IsOnCurrentThread(bool* aResult)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP_(bool)
|
||||
WebSocketImpl::IsOnCurrentThreadInfallible()
|
||||
{
|
||||
return IsTargetThread();
|
||||
}
|
||||
|
||||
bool
|
||||
WebSocketImpl::IsTargetThread() const
|
||||
{
|
||||
|
|
|
@ -1718,20 +1718,25 @@ public:
|
|||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHOD_(bool) IsOnCurrentThreadInfallible() override
|
||||
{
|
||||
MutexAutoLock lock(mMutex);
|
||||
|
||||
if (!mWorkerPrivate) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return mWorkerPrivate->IsOnCurrentThread();
|
||||
}
|
||||
|
||||
NS_IMETHOD
|
||||
IsOnCurrentThread(bool* aIsOnCurrentThread) override
|
||||
{
|
||||
MOZ_ASSERT(aIsOnCurrentThread);
|
||||
MutexAutoLock lock(mMutex);
|
||||
|
||||
if (!mWorkerPrivate) {
|
||||
*aIsOnCurrentThread = false;
|
||||
*aIsOnCurrentThread = IsOnCurrentThreadInfallible();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
return mWorkerPrivate->IsOnCurrentThread(aIsOnCurrentThread);
|
||||
}
|
||||
|
||||
NS_DECL_THREADSAFE_ISUPPORTS
|
||||
};
|
||||
|
||||
|
@ -5360,16 +5365,13 @@ WorkerPrivate::InterruptCallback(JSContext* aCx)
|
|||
return true;
|
||||
}
|
||||
|
||||
nsresult
|
||||
WorkerPrivate::IsOnCurrentThread(bool* aIsOnCurrentThread)
|
||||
bool
|
||||
WorkerPrivate::IsOnCurrentThread()
|
||||
{
|
||||
// May be called on any thread!
|
||||
|
||||
MOZ_ASSERT(aIsOnCurrentThread);
|
||||
MOZ_ASSERT(mPRThread);
|
||||
|
||||
*aIsOnCurrentThread = PR_GetCurrentThread() == mPRThread;
|
||||
return NS_OK;
|
||||
return PR_GetCurrentThread() == mPRThread;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -7102,12 +7104,25 @@ EventTarget::IsOnCurrentThread(bool* aIsOnCurrentThread)
|
|||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
nsresult rv = mWorkerPrivate->IsOnCurrentThread(aIsOnCurrentThread);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
*aIsOnCurrentThread = mWorkerPrivate->IsOnCurrentThread();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
template <class Derived>
|
||||
NS_IMETHODIMP_(bool)
|
||||
WorkerPrivateParent<Derived>::
|
||||
EventTarget::IsOnCurrentThreadInfallible()
|
||||
{
|
||||
// May be called on any thread!
|
||||
|
||||
MutexAutoLock lock(mMutex);
|
||||
|
||||
if (!mWorkerPrivate) {
|
||||
NS_WARNING("A worker's event target was used after the worker has !");
|
||||
return false;
|
||||
}
|
||||
|
||||
return mWorkerPrivate->IsOnCurrentThread();
|
||||
}
|
||||
|
||||
BEGIN_WORKERS_NAMESPACE
|
||||
|
|
|
@ -1158,8 +1158,8 @@ public:
|
|||
bool
|
||||
InterruptCallback(JSContext* aCx);
|
||||
|
||||
nsresult
|
||||
IsOnCurrentThread(bool* aIsOnCurrentThread);
|
||||
bool
|
||||
IsOnCurrentThread();
|
||||
|
||||
bool
|
||||
CloseInternal(JSContext* aCx)
|
||||
|
|
|
@ -173,6 +173,14 @@ nsSocketTransportService::IsOnCurrentThread(bool *result)
|
|||
return thread->IsOnCurrentThread(result);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP_(bool)
|
||||
nsSocketTransportService::IsOnCurrentThreadInfallible()
|
||||
{
|
||||
nsCOMPtr<nsIThread> thread = GetThreadSafely();
|
||||
NS_ENSURE_TRUE(thread, false);
|
||||
return thread->IsOnCurrentThread();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// socket api (socket thread only)
|
||||
|
||||
|
|
|
@ -496,6 +496,20 @@ nsStreamTransportService::DelayedDispatch(already_AddRefed<nsIRunnable>, uint32_
|
|||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP_(bool)
|
||||
nsStreamTransportService::IsOnCurrentThreadInfallible()
|
||||
{
|
||||
nsCOMPtr<nsIThreadPool> pool;
|
||||
{
|
||||
mozilla::MutexAutoLock lock(mShutdownLock);
|
||||
pool = mPool;
|
||||
}
|
||||
if (!pool) {
|
||||
return false;
|
||||
}
|
||||
return pool->IsOnCurrentThread();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsStreamTransportService::IsOnCurrentThread(bool *result)
|
||||
{
|
||||
|
|
|
@ -441,6 +441,16 @@ LazyIdleThread::IsOnCurrentThread(bool* aIsOnCurrentThread)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP_(bool)
|
||||
LazyIdleThread::IsOnCurrentThreadInfallible()
|
||||
{
|
||||
if (mThread) {
|
||||
return mThread->IsOnCurrentThread();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
LazyIdleThread::GetPRThread(PRThread** aPRThread)
|
||||
{
|
||||
|
|
|
@ -161,6 +161,12 @@ SchedulerEventTarget::IsOnCurrentThread(bool* aIsOnCurrentThread)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP_(bool)
|
||||
SchedulerEventTarget::IsOnCurrentThreadInfallible()
|
||||
{
|
||||
return NS_IsMainThread();
|
||||
}
|
||||
|
||||
/* static */ nsresult
|
||||
SchedulerGroup::UnlabeledDispatch(const char* aName,
|
||||
TaskCategory aCategory,
|
||||
|
|
|
@ -77,6 +77,8 @@ public:
|
|||
|
||||
NS_IMETHOD IsOnCurrentThread(bool *_retval) override { return !mEventTarget ? NS_ERROR_NULL_POINTER : mEventTarget->IsOnCurrentThread(_retval); }
|
||||
|
||||
NS_IMETHOD_(bool) IsOnCurrentThreadInfallible() override { return mEventTarget && mEventTarget->IsOnCurrentThread(); }
|
||||
|
||||
// Creates necessary statics. Called once at startup.
|
||||
static void InitStatics();
|
||||
|
||||
|
|
|
@ -56,6 +56,12 @@ public:
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHOD_(bool)
|
||||
IsOnCurrentThreadInfallible() override
|
||||
{
|
||||
return mTaskQueue->mTarget->IsOnCurrentThread();
|
||||
}
|
||||
|
||||
NS_DECL_THREADSAFE_ISUPPORTS
|
||||
};
|
||||
|
||||
|
|
|
@ -363,10 +363,10 @@ public:
|
|||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
nsresult
|
||||
IsOnCurrentThread(bool* aResult)
|
||||
bool
|
||||
IsOnCurrentThread()
|
||||
{
|
||||
return mBaseTarget->IsOnCurrentThread(aResult);
|
||||
return mBaseTarget->IsOnCurrentThread();
|
||||
}
|
||||
|
||||
NS_DECL_THREADSAFE_ISUPPORTS
|
||||
|
@ -450,7 +450,14 @@ ThrottledEventQueue::DelayedDispatch(already_AddRefed<nsIRunnable> aEvent,
|
|||
NS_IMETHODIMP
|
||||
ThrottledEventQueue::IsOnCurrentThread(bool* aResult)
|
||||
{
|
||||
return mInner->IsOnCurrentThread(aResult);
|
||||
*aResult = mInner->IsOnCurrentThread();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP_(bool)
|
||||
ThrottledEventQueue::IsOnCurrentThreadInfallible()
|
||||
{
|
||||
return mInner->IsOnCurrentThread();
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
|
||||
native alreadyAddRefed_nsIRunnable(already_AddRefed<nsIRunnable>);
|
||||
|
||||
[scriptable, uuid(a03b8b63-af8b-4164-b0e5-c41e8b2b7cfa)]
|
||||
[builtinclass, scriptable, uuid(a03b8b63-af8b-4164-b0e5-c41e8b2b7cfa)]
|
||||
interface nsIEventTarget : nsISupports
|
||||
{
|
||||
/* until we can get rid of all uses, keep the non-alreadyAddRefed<> version */
|
||||
|
@ -53,13 +53,51 @@ interface nsIEventTarget : nsISupports
|
|||
const unsigned long DISPATCH_AT_END = 2;
|
||||
|
||||
/**
|
||||
* Check to see if this event target is associated with the current thread.
|
||||
* IsOnCurrentThread() should return true if events dispatched to this target
|
||||
* can possibly run on the current thread, and false otherwise. In the case
|
||||
* of an nsIEventTarget for a thread pool, it should return true on all
|
||||
* threads in the pool. In the case of a non-thread nsIEventTarget such as
|
||||
* ThrottledEventQueue, it should return true on the thread where events are
|
||||
* expected to be processed, even if no events from the queue are actually
|
||||
* being processed right now.
|
||||
*
|
||||
* @returns
|
||||
* A boolean value that if "true" indicates that events dispatched to this
|
||||
* event target will run on the current thread (i.e., the thread calling
|
||||
* this method).
|
||||
* When called on an nsISerialEventTarget, IsOnCurrentThread can be used to
|
||||
* ensure that no other thread has "ownership" of the event target. As such,
|
||||
* it's useful for asserting that an object is only used on a particular
|
||||
* thread. IsOnCurrentThread can't guarantee that the current event has been
|
||||
* dispatched through a particular event target.
|
||||
*
|
||||
* The infallible version of IsOnCurrentThread() is optimized to avoid a
|
||||
* virtual call for non-thread event targets. Thread targets should set
|
||||
* mVirtualThread to their virtual PRThread. Non-thread targets should leave
|
||||
* mVirtualThread null and implement IsOnCurrentThreadInfallible() to
|
||||
* return the correct answer.
|
||||
*
|
||||
* The fallible version of IsOnCurrentThread may return errors, such as during
|
||||
* shutdown. If it does not return an error, it should return the same result
|
||||
* as the infallible version. The infallible method should return the correct
|
||||
* result regardless of whether the fallible method returns an error.
|
||||
*/
|
||||
%{C++
|
||||
public:
|
||||
// Infallible. Defined in nsThreadUtils.cpp. Delegates to
|
||||
// IsOnCurrentThreadInfallible when mVirtualThread is null.
|
||||
bool IsOnCurrentThread();
|
||||
|
||||
protected:
|
||||
PRThread* mVirtualThread;
|
||||
|
||||
nsIEventTarget() : mVirtualThread(nullptr) {}
|
||||
%}
|
||||
// Note that this method is protected. We define it through IDL, rather than
|
||||
// in a %{C++ block, to ensure that the correct method indices are recorded
|
||||
// for XPConnect purposes.
|
||||
[noscript,notxpcom] boolean isOnCurrentThreadInfallible();
|
||||
%{C++
|
||||
public:
|
||||
%}
|
||||
|
||||
// Fallible version of IsOnCurrentThread.
|
||||
boolean isOnCurrentThread();
|
||||
|
||||
/**
|
||||
|
@ -129,6 +167,7 @@ interface nsIEventTarget : nsISupports
|
|||
// Convenient NS_DECL variant that includes some C++-only methods.
|
||||
#define NS_DECL_NSIEVENTTARGET_FULL \
|
||||
NS_DECL_NSIEVENTTARGET \
|
||||
/* Avoid hiding this method */ \
|
||||
using nsIEventTarget::Dispatch;
|
||||
/* Avoid hiding these methods */ \
|
||||
using nsIEventTarget::Dispatch; \
|
||||
using nsIEventTarget::IsOnCurrentThread;
|
||||
%}
|
||||
|
|
|
@ -24,7 +24,7 @@ native alreadyAddRefed_nsIIdlePeriod(already_AddRefed<nsIIdlePeriod>);
|
|||
*
|
||||
* See nsIThreadManager for the API used to create and locate threads.
|
||||
*/
|
||||
[scriptable, uuid(5801d193-29d1-4964-a6b7-70eb697ddf2b)]
|
||||
[builtinclass, scriptable, uuid(5801d193-29d1-4964-a6b7-70eb697ddf2b)]
|
||||
interface nsIThread : nsIEventTarget
|
||||
{
|
||||
/**
|
||||
|
|
|
@ -13,7 +13,7 @@ interface nsIThreadObserver;
|
|||
* The XPCOM thread object implements this interface, which allows a consumer
|
||||
* to observe dispatch activity on the thread.
|
||||
*/
|
||||
[scriptable, uuid(a3a72e5f-71d9-4add-8f30-59a78fb6d5eb)]
|
||||
[builtinclass, scriptable, uuid(a3a72e5f-71d9-4add-8f30-59a78fb6d5eb)]
|
||||
interface nsIThreadInternal : nsIThread
|
||||
{
|
||||
/**
|
||||
|
|
|
@ -27,7 +27,7 @@ interface nsIThreadPoolListener : nsISupports
|
|||
* anonymous (unnamed) worker threads. An event dispatched to the thread pool
|
||||
* will be run on the next available worker thread.
|
||||
*/
|
||||
[scriptable, uuid(76ce99c9-8e43-489a-9789-f27cc4424965)]
|
||||
[builtinclass, scriptable, uuid(76ce99c9-8e43-489a-9789-f27cc4424965)]
|
||||
interface nsIThreadPool : nsIEventTarget
|
||||
{
|
||||
/**
|
||||
|
|
|
@ -459,6 +459,7 @@ nsThread::ThreadFunc(void* aArg)
|
|||
nsThread* self = initData->thread; // strong reference
|
||||
|
||||
self->mThread = PR_GetCurrentThread();
|
||||
self->mVirtualThread = GetCurrentVirtualThread();
|
||||
SetupCurrentThreadForChaosMode();
|
||||
|
||||
if (!initData->name.IsEmpty()) {
|
||||
|
@ -705,6 +706,7 @@ nsresult
|
|||
nsThread::InitCurrentThread()
|
||||
{
|
||||
mThread = PR_GetCurrentThread();
|
||||
mVirtualThread = GetCurrentVirtualThread();
|
||||
SetupCurrentThreadForChaosMode();
|
||||
|
||||
mIdlePeriod = new IdlePeriod();
|
||||
|
@ -889,6 +891,13 @@ nsThread::IsOnCurrentThread(bool* aResult)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP_(bool)
|
||||
nsThread::IsOnCurrentThreadInfallible()
|
||||
{
|
||||
// Rely on mVirtualThread being correct.
|
||||
MOZ_CRASH("IsOnCurrentThreadInfallible should never be called on nsIThread");
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// nsIThread
|
||||
|
||||
|
@ -1685,3 +1694,9 @@ nsThread::nsNestedEventTarget::IsOnCurrentThread(bool* aResult)
|
|||
{
|
||||
return mThread->IsOnCurrentThread(aResult);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP_(bool)
|
||||
nsThread::nsNestedEventTarget::IsOnCurrentThreadInfallible()
|
||||
{
|
||||
return mThread->IsOnCurrentThread();
|
||||
}
|
||||
|
|
|
@ -282,6 +282,20 @@ nsThreadPool::DelayedDispatch(already_AddRefed<nsIRunnable>, uint32_t)
|
|||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP_(bool)
|
||||
nsThreadPool::IsOnCurrentThreadInfallible()
|
||||
{
|
||||
MutexAutoLock lock(mMutex);
|
||||
|
||||
nsIThread* thread = NS_GetCurrentThread();
|
||||
for (uint32_t i = 0; i < static_cast<uint32_t>(mThreads.Count()); ++i) {
|
||||
if (mThreads[i] == thread) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsThreadPool::IsOnCurrentThread(bool* aResult)
|
||||
{
|
||||
|
|
|
@ -545,3 +545,12 @@ GetCurrentPhysicalThread()
|
|||
}
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
bool
|
||||
nsIEventTarget::IsOnCurrentThread()
|
||||
{
|
||||
if (mVirtualThread) {
|
||||
return mVirtualThread == GetCurrentVirtualThread();
|
||||
}
|
||||
return IsOnCurrentThreadInfallible();
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче