Commit fcebb0df authored by Nate Chapin's avatar Nate Chapin Committed by Commit Bot

Add a generic way to run a task on all WorkerThreads

This allows us to hide the HashSet of all current WorkerThreads, which
is valuable since the callers outside WorkerThread don't have access to
the necessary mutex to access it safely.

Convert TimeZoneMonitorClient to use this helper.

Change-Id: I5aa743a1fa0c789a8f9496a05d7cfecde9238004
Reviewed-on: https://chromium-review.googlesource.com/1228950Reviewed-by: default avatarHiroki Nakagawa <nhiroki@chromium.org>
Reviewed-by: default avatarMark Mentovai <mark@chromium.org>
Commit-Queue: Nate Chapin <japhet@chromium.org>
Cr-Commit-Position: refs/heads/master@{#592116}
parent 29028a2d
...@@ -72,7 +72,7 @@ constexpr TimeDelta kForcibleTerminationDelay = TimeDelta::FromSeconds(2); ...@@ -72,7 +72,7 @@ constexpr TimeDelta kForcibleTerminationDelay = TimeDelta::FromSeconds(2);
} // namespace } // namespace
static Mutex& ThreadSetMutex() { Mutex& WorkerThread::ThreadSetMutex() {
DEFINE_THREAD_SAFE_STATIC_LOCAL(Mutex, mutex, ()); DEFINE_THREAD_SAFE_STATIC_LOCAL(Mutex, mutex, ());
return mutex; return mutex;
} }
......
...@@ -136,6 +136,7 @@ class CORE_EXPORT WorkerThread : public WebThread::TaskObserver { ...@@ -136,6 +136,7 @@ class CORE_EXPORT WorkerThread : public WebThread::TaskObserver {
// workers are shut down. Please be careful when using this function, because // workers are shut down. Please be careful when using this function, because
// after the synchronous termination any V8 APIs may suddenly start to return // after the synchronous termination any V8 APIs may suddenly start to return
// empty handles and it may cause crashes. // empty handles and it may cause crashes.
// WARNING: This is not safe if a nested worker is running.
static void TerminateAllWorkersForTesting(); static void TerminateAllWorkersForTesting();
// WebThread::TaskObserver. // WebThread::TaskObserver.
...@@ -182,9 +183,19 @@ class CORE_EXPORT WorkerThread : public WebThread::TaskObserver { ...@@ -182,9 +183,19 @@ class CORE_EXPORT WorkerThread : public WebThread::TaskObserver {
// Number of active worker threads. // Number of active worker threads.
static unsigned WorkerThreadCount(); static unsigned WorkerThreadCount();
// Returns a set of all worker threads. This must be called only on the main // Runs |function| with |parameters| on each worker thread, and
// thread and the returned set must not be stored for future use. // adds the current WorkerThread* as the first parameter |function|.
static HashSet<WorkerThread*>& WorkerThreads(); template <typename FunctionType, typename... Parameters>
static void CallOnAllWorkerThreads(FunctionType function,
Parameters&&... parameters) {
MutexLocker lock(ThreadSetMutex());
for (WorkerThread* thread : WorkerThreads()) {
PostCrossThreadTask(
*thread->GetTaskRunner(TaskType::kInternalWorker), FROM_HERE,
CrossThreadBind(function, WTF::CrossThreadUnretained(thread),
parameters...));
}
}
int GetWorkerThreadId() const { return worker_thread_id_; } int GetWorkerThreadId() const { return worker_thread_id_; }
...@@ -240,6 +251,9 @@ class CORE_EXPORT WorkerThread : public WebThread::TaskObserver { ...@@ -240,6 +251,9 @@ class CORE_EXPORT WorkerThread : public WebThread::TaskObserver {
FRIEND_TEST_ALL_PREFIXES(WorkerThreadTest, FRIEND_TEST_ALL_PREFIXES(WorkerThreadTest,
Terminate_WhileDebuggerTaskIsRunning); Terminate_WhileDebuggerTaskIsRunning);
static HashSet<WorkerThread*>& WorkerThreads();
static Mutex& ThreadSetMutex();
// Represents the state of this worker thread. // Represents the state of this worker thread.
enum class ThreadState { enum class ThreadState {
kNotStarted, kNotStarted,
......
...@@ -65,21 +65,7 @@ void TimeZoneMonitorClient::OnTimeZoneChange(const String& time_zone_info) { ...@@ -65,21 +65,7 @@ void TimeZoneMonitorClient::OnTimeZoneChange(const String& time_zone_info) {
} }
NotifyTimezoneChangeToV8(V8PerIsolateData::MainThreadIsolate()); NotifyTimezoneChangeToV8(V8PerIsolateData::MainThreadIsolate());
WorkerThread::CallOnAllWorkerThreads(&NotifyTimezoneChangeOnWorkerThread);
HashSet<WorkerThread*>& threads = WorkerThread::WorkerThreads();
HashSet<WorkerBackingThread*> posted;
for (WorkerThread* thread : threads) {
// Ensure every WorkerBackingThread(holding one platform thread) only get
// the task posted once, because one WorkerBackingThread could be shared
// among multiple WorkerThreads.
if (posted.Contains(&thread->GetWorkerBackingThread()))
continue;
PostCrossThreadTask(*thread->GetTaskRunner(TaskType::kInternalDefault),
FROM_HERE,
CrossThreadBind(&NotifyTimezoneChangeOnWorkerThread,
WTF::CrossThreadUnretained(thread)));
posted.insert(&thread->GetWorkerBackingThread());
}
} }
} // namespace blink } // namespace blink
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment