Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(4041)

Unified Diff: base/task_scheduler/scheduler_single_thread_task_runner_manager.cc

Issue 2765703002: Add the COM STA Task Runner (Closed)
Patch Set: Created 3 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: base/task_scheduler/scheduler_single_thread_task_runner_manager.cc
diff --git a/base/task_scheduler/scheduler_single_thread_task_runner_manager.cc b/base/task_scheduler/scheduler_single_thread_task_runner_manager.cc
index 6a2676fb49b9e20bb8f06ea8b52a4839a76a8922..38c796a43d55e5883d730b0121963aead468d35e 100644
--- a/base/task_scheduler/scheduler_single_thread_task_runner_manager.cc
+++ b/base/task_scheduler/scheduler_single_thread_task_runner_manager.cc
@@ -22,6 +22,13 @@
#include "base/task_scheduler/task_traits.h"
#include "base/threading/platform_thread.h"
#include "base/time/time.h"
+#include "build/build_config.h"
fdoray 2017/03/21 15:23:12 Not needed if you include it in the .h.
robliao 2017/03/21 20:00:19 Done.
+
+#if defined(OS_WIN)
+#include <windows.h>
+
+#include "base/win/scoped_com_initializer.h"
+#endif
gab 2017/03/21 21:09:34 #endif // defined(OS_WIN)
robliao 2017/03/21 22:25:32 Ah, I thought we didn't want these for certain sho
gab 2017/03/22 16:16:04 Yeah, it's kind of an hand-wavy rule, for tight sc
namespace base {
namespace internal {
@@ -129,6 +136,103 @@ class SchedulerWorkerDelegate : public SchedulerWorker::Delegate {
DISALLOW_COPY_AND_ASSIGN(SchedulerWorkerDelegate);
};
+#if defined(OS_WIN)
+
+class SchedulerWorkerCOMDelegate : public SchedulerWorkerDelegate {
+ public:
+ SchedulerWorkerCOMDelegate(const std::string& thread_name,
+ TaskTracker* task_tracker)
+ : SchedulerWorkerDelegate(thread_name), task_tracker_(task_tracker) {}
fdoray 2017/03/21 15:23:12 ~SchedulerWorkerCOMDelegate() { DCHECK(!scoped_c
robliao 2017/03/21 20:00:20 Done.
+
+ // SchedulerWorker::Delegate:
+ void OnMainEntry(SchedulerWorker* worker) override {
+ SchedulerWorkerDelegate::OnMainEntry(worker);
+
+ scoped_com_initializer_ = MakeUnique<win::ScopedCOMInitializer>();
+ }
+
+ scoped_refptr<Sequence> GetWork(SchedulerWorker* worker) override {
+ // This scheme below allows us to cover the following scenarios:
+ // * Tasks only come from SchedulerWorkerDelegate::GetWork():
gab 2017/03/21 21:09:34 s/only come/are only coming/ here and below? Fee
robliao 2017/03/21 22:25:32 Rephrased // This scheme below allows us to co
+ // Only return the sequence from GetWork().
+ // * Tasks only come from the Windows Message Queue:
+ // Only return the sequence from GetWorkFromWindowsMessageQueue();
+ // * Tasks come from both SchedulerWorkerDelegate::GetWork() and
+ // the Windows Message Queue:
+ // Process sequences from each source round-robin style.
+ scoped_refptr<Sequence> sequence;
+ if (get_work_first_) {
+ sequence = SchedulerWorkerDelegate::GetWork(worker);
+ if (sequence)
+ get_work_first_ = false;
+ }
+
+ if (!sequence) {
+ sequence = GetWorkFromWindowsMessageQueue();
+ if (sequence)
+ get_work_first_ = true;
+ }
+
+ if (!sequence && !get_work_first_) {
+ // This case is important if we checked the Windows Message Queue first
+ // and found there was no work. We don't want to return null immediately
+ // as that could cause the thread to go to sleep while work is waiting via
+ // SchedulerWorkerDelegate::GetWork(). As the same time, we don't want to
gab 2017/03/21 21:09:33 s/As/At/ (but overall I don't think this last sen
robliao 2017/03/21 22:25:32 Removed.
+ // mark |get_work_first_| to continue to check the message queue first
+ // after this sequence is returned.
+ sequence = SchedulerWorkerDelegate::GetWork(worker);
+ }
+ return sequence;
+ }
+
+ void OnMainExit() override { scoped_com_initializer_.reset(); }
+
+ void WaitForWork(WaitableEvent* wake_up_event) override {
+ DCHECK(wake_up_event);
+ const TimeDelta sleep_time = GetSleepTimeout();
+ const DWORD milliseconds_wait =
+ sleep_time.is_max() ? INFINITE : sleep_time.InMilliseconds();
+ HANDLE wake_up_event_handle = wake_up_event->handle();
+ DWORD result = MsgWaitForMultipleObjectsEx(
+ 1, &wake_up_event_handle, milliseconds_wait, QS_ALLINPUT, 0);
+ if (result == WAIT_OBJECT_0) {
+ // Reset the event since we woke up due to it.
+ wake_up_event->Reset();
+ }
+ }
fdoray 2017/03/21 15:23:12 void ReEnqueueSequence(scoped_refptr<Sequence> seq
robliao 2017/03/21 20:00:19 This check is already covered by SchedulerWorkerDe
+
+ private:
+ scoped_refptr<Sequence> GetWorkFromWindowsMessageQueue() {
+ MSG msg;
+ if (PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE) != FALSE) {
+ auto pump_message_task =
+ MakeUnique<Task>(FROM_HERE,
+ base::Bind(
+ [](MSG msg_in) {
+ MSG msg = msg_in;
gab 2017/03/21 21:09:34 Why do you need this extra variable?
robliao 2017/03/21 22:25:32 Because in the shuffle I lost a "const MSG& msg_in
gab 2017/03/22 16:16:04 sgtm
+ TranslateMessage(&msg);
+ DispatchMessage(&msg);
+ },
+ msg),
gab 2017/03/21 21:09:34 std::move(msg) ? Not sure if MSG is moveable but i
robliao 2017/03/21 22:25:32 sgtm. No qualms with that. It is just a struct und
+ TaskTraits().MayBlock(), TimeDelta());
+ if (task_tracker_->WillPostTask(pump_message_task.get())) {
gab 2017/03/21 21:09:33 Otherwise do we have to tell Windows we're droppin
robliao 2017/03/21 22:25:32 Generally, the only thing you can do with a messag
gab 2017/03/22 16:16:04 Got it, and I guess SendMessage would return with
robliao 2017/03/22 17:56:52 Hrm... that's a good question. One of the things a
+ message_pump_sequence_->PushTask(std::move(pump_message_task));
fdoray 2017/03/21 15:23:12 bool was_empty = message_pump_sequence_->PushTask(
robliao 2017/03/21 20:00:19 Done.
+ return message_pump_sequence_;
+ }
+ }
+ return nullptr;
+ }
+
+ bool get_work_first_ = true;
+ scoped_refptr<Sequence> message_pump_sequence_ = new Sequence;
fdoray 2017/03/21 15:23:12 >>const<< scoped_refptr<Sequence> message_pump_seq
robliao 2017/03/21 20:00:19 Done.
+ TaskTracker* const task_tracker_;
+ std::unique_ptr<win::ScopedCOMInitializer> scoped_com_initializer_;
+
+ DISALLOW_COPY_AND_ASSIGN(SchedulerWorkerCOMDelegate);
+};
+
+#endif // defined(OS_WIN)
+
} // namespace
class SchedulerSingleThreadTaskRunnerManager::SchedulerSingleThreadTaskRunner
@@ -241,9 +345,23 @@ SchedulerSingleThreadTaskRunnerManager::CreateSingleThreadTaskRunnerWithTraits(
DCHECK_LT(index, worker_pool_params_vector_.size());
return new SchedulerSingleThreadTaskRunner(
this, traits,
- CreateAndRegisterSchedulerWorker(worker_pool_params_vector_[index]));
+ CreateAndRegisterSchedulerWorker(worker_pool_params_vector_[index],
+ DelegateType::REGULAR));
}
+#if defined(OS_WIN)
+scoped_refptr<SingleThreadTaskRunner>
+SchedulerSingleThreadTaskRunnerManager::CreateCOMSTATaskRunnerWithTraits(
+ const TaskTraits& traits) {
+ size_t index = worker_pool_index_for_traits_callback_.Run(traits);
+ DCHECK_LT(index, worker_pool_params_vector_.size());
+ return new SchedulerSingleThreadTaskRunner(
+ this, traits,
+ CreateAndRegisterSchedulerWorker(worker_pool_params_vector_[index],
+ DelegateType::COM_STA));
+}
+#endif // defined(OS_WIN)
+
void SchedulerSingleThreadTaskRunnerManager::JoinForTesting() {
decltype(workers_) local_workers;
{
@@ -264,11 +382,27 @@ void SchedulerSingleThreadTaskRunnerManager::JoinForTesting() {
SchedulerWorker*
SchedulerSingleThreadTaskRunnerManager::CreateAndRegisterSchedulerWorker(
- const SchedulerWorkerPoolParams& params) {
+ const SchedulerWorkerPoolParams& params,
+ DelegateType delegate_type) {
AutoSchedulerLock auto_lock(workers_lock_);
int id = next_worker_id_++;
- auto delegate = MakeUnique<SchedulerWorkerDelegate>(base::StringPrintf(
- "TaskSchedulerSingleThreadWorker%d%s", id, params.name().c_str()));
+
+ std::unique_ptr<SchedulerWorkerDelegate> delegate;
fdoray 2017/03/21 15:23:12 Optional: - Instantiate the right type of delegate
robliao 2017/03/21 20:00:19 I guess this comes down to how much duplication we
gab 2017/03/21 21:09:34 Or we make CreateAndRegisterSchedulerWorker<T> a t
robliao 2017/03/21 22:25:32 That is an interesting idea, but SchedulerWorkerCO
robliao 2017/03/22 08:29:42 I think I just came up with a scheme to make this
+ switch (delegate_type) {
+ case DelegateType::REGULAR:
+ delegate = MakeUnique<SchedulerWorkerDelegate>(base::StringPrintf(
+ "TaskSchedulerSingleThreadWorker%d%s", id, params.name().c_str()));
+ break;
+#if defined(OS_WIN)
+ case DelegateType::COM_STA:
+ delegate = MakeUnique<SchedulerWorkerCOMDelegate>(
+ base::StringPrintf("TaskSchedulerSingleThreadWorker%d%sCOMSTA", id,
+ params.name().c_str()),
+ task_tracker_);
+ break;
+#endif
+ }
+
workers_.emplace_back(SchedulerWorker::Create(
params.priority_hint(), std::move(delegate), task_tracker_,
SchedulerWorker::InitialState::DETACHED));

Powered by Google App Engine
This is Rietveld 408576698