Bug 1800213 - Add a flag for creating nsThreads with a NONMAINUITHREAD MessageLoop. r=xpcom-reviewers,nika

Differential Revision: https://phabricator.services.mozilla.com/D166062
This commit is contained in:
Andreas Pehrson 2023-02-28 14:32:42 +00:00
parent 07d7c2dcab
commit a1396c7b11
5 changed files with 59 additions and 3 deletions

View File

@ -18,6 +18,11 @@
#include "mozilla/SyncRunnable.h"
#include "gtest/gtest.h"
#ifdef XP_WIN
# include <windef.h>
# include <winuser.h>
#endif
using namespace mozilla;
class nsRunner final : public Runnable {
@ -377,3 +382,34 @@ TEST(Threads, UnregisteredShutdownTask)
thread->Shutdown();
}
#if defined(XP_WIN) || !defined(DEBUG)
TEST(Threads, OptionsIsUiThread)
{
// On Windows, test that the isUiThread flag results in a GUI thread.
// In non-Windows non-debug builds, test that the isUiThread flag is ignored.
nsCOMPtr<nsIThread> thread;
nsIThreadManager::ThreadCreationOptions options;
options.isUiThread = true;
MOZ_ALWAYS_SUCCEEDS(NS_NewNamedThread(
"Testing Thread", getter_AddRefs(thread), nullptr, options));
bool isGuiThread = false;
auto syncRunnable =
MakeRefPtr<SyncRunnable>(NS_NewRunnableFunction(__func__, [&] {
# ifdef XP_WIN
isGuiThread = ::IsGUIThread(false);
# endif
}));
MOZ_ALWAYS_SUCCEEDS(syncRunnable->DispatchToThread(thread));
bool expectGuiThread = false;
# ifdef XP_WIN
expectGuiThread = true;
# endif
EXPECT_EQ(expectGuiThread, isGuiThread);
thread->Shutdown();
}
#endif

View File

@ -68,6 +68,10 @@ interface nsIThreadManager : nsISupports
// and perform their own event dispatching internaly, such as thread pool
// threads or the timer thread.
bool blockDispatch = false;
// (Windows-only) Whether the thread should have a MessageLoop capable of
// processing native UI events. Defaults to false.
bool isUiThread = false;
};
%}

View File

@ -378,7 +378,14 @@ void nsThread::ThreadFunc(void* aArg) {
{
// Scope for MessageLoop.
MessageLoop loop(MessageLoop::TYPE_MOZILLA_NONMAINTHREAD, self);
MessageLoop loop(
#ifdef XP_WIN
self->mIsUiThread ? MessageLoop::TYPE_MOZILLA_NONMAINUITHREAD
: MessageLoop::TYPE_MOZILLA_NONMAINTHREAD,
#else
MessageLoop::TYPE_MOZILLA_NONMAINTHREAD,
#endif
self);
// Now, process incoming events...
loop.Run();
@ -560,13 +567,19 @@ nsThread::nsThread(NotNull<SynchronizedEventQueue*> aQueue,
mPriority(PRIORITY_NORMAL),
mIsMainThread(aMainThread == MAIN_THREAD),
mUseHangMonitor(aMainThread == MAIN_THREAD),
mIsUiThread(aOptions.isUiThread),
mIsAPoolThreadFree(nullptr),
mCanInvokeJS(false),
#ifdef EARLY_BETA_OR_EARLIER
mLastWakeupCheckTime(TimeStamp::Now()),
#endif
mPerformanceCounterState(mNestedEventLoopDepth, mIsMainThread) {
#ifndef XP_WIN
MOZ_ASSERT(!mIsUiThread, "Non-main UI threads are only supported on Windows");
#endif
if (mIsMainThread) {
MOZ_ASSERT(!mIsUiThread,
"Setting isUIThread is not supported for main threads");
mozilla::TaskController::Get()->SetPerformanceCounterState(
&mPerformanceCounterState);
}
@ -585,6 +598,7 @@ nsThread::nsThread()
mPriority(PRIORITY_NORMAL),
mIsMainThread(false),
mUseHangMonitor(false),
mIsUiThread(false),
mCanInvokeJS(false),
#ifdef EARLY_BETA_OR_EARLIER
mLastWakeupCheckTime(TimeStamp::Now()),

View File

@ -315,6 +315,7 @@ class nsThread : public nsIThreadInternal,
const bool mIsMainThread;
bool mUseHangMonitor;
const bool mIsUiThread;
mozilla::Atomic<bool, mozilla::Relaxed>* mIsAPoolThreadFree;
// Set to true if this thread creates a JSRuntime.

View File

@ -48,8 +48,9 @@ class nsIThread;
* The resulting nsIThread object.
* @param aInitialEvent
* The initial event to run on this thread. This parameter may be null.
* @param aStackSize
* The size in bytes to reserve for the thread's stack.
* @param aOptions
* Options used to configure thread creation.
* Options are documented in nsIThreadManager.idl.
*
* @returns NS_ERROR_INVALID_ARG
* Indicates that the given name is not unique.