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

Side by Side Diff: media/midi/task_service.cc

Issue 2741713002: Web MIDI: implement TaskService (Closed)
Patch Set: fix Created 3 years, 6 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 unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2017 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "media/midi/task_service.h"
6
7 #include "base/strings/stringprintf.h"
8 #include "base/threading/thread_task_runner_handle.h"
9
10 namespace midi {
11
12 namespace {
13
14 constexpr TaskService::InstanceId kInvalidInstanceId = -1;
15 constexpr TaskService::RunnerId kReplyRunnerId = -1;
16
17 } // namespace
18
19 TaskService::TaskService()
20 : next_instance_id_(0), bound_instance_id_(kInvalidInstanceId) {}
21
22 TaskService::~TaskService() {
23 base::AutoLock lock(lock_);
24 threads_.clear();
25 }
26
27 bool TaskService::BindInstance() {
28 {
29 base::AutoLock instance_lock(instance_lock_);
30 if (bound_instance_id_ != kInvalidInstanceId)
31 return false;
32 bound_instance_id_ = next_instance_id_++;
33 }
34 base::AutoLock lock(lock_);
35 DCHECK(!reply_task_runner_);
36 reply_task_runner_ = base::ThreadTaskRunnerHandle::Get();
37 return true;
38 }
39
40 bool TaskService::UnbindInstance() {
41 {
42 base::AutoLock instance_lock(instance_lock_);
43 if (bound_instance_id_ == kInvalidInstanceId)
44 return false;
45 bound_instance_id_ = kInvalidInstanceId;
46 }
47 base::AutoLock lock(lock_);
48 DCHECK(reply_task_runner_);
49 reply_task_runner_ = nullptr;
50 // Now RunTask never run any posted task. But invoked tasks might be still
yhirano 2017/06/08 09:03:38 [optional] "From now on RunTask will never run any
Takashi Toyoshima 2017/06/08 10:30:11 Done.
51 // running here. To ensure no task run before quiting this method, take all
52 // |thread_task_locks_| once.
53 for (auto& task_lock : thread_task_locks_)
54 base::AutoLock auto_task_lock(*task_lock);
55 base::AutoLock reply_lock(reply_task_lock_);
56 return true;
57 }
58
59 void TaskService::PostStaticTask(RunnerId runner, base::OnceClosure task) {
60 base::AutoLock lock(lock_);
61 GetTaskRunner(runner)->PostTask(FROM_HERE, std::move(task));
62 }
63
64 void TaskService::PostBoundTask(RunnerId runner, base::OnceClosure task) {
65 base::AutoLock instance_lock(instance_lock_);
66 if (bound_instance_id_ == kInvalidInstanceId)
67 return;
68 base::AutoLock lock(lock_);
69 GetTaskRunner(runner)->PostTask(
70 FROM_HERE, base::BindOnce(&TaskService::RunTask, base::Unretained(this),
71 bound_instance_id_, runner, std::move(task)));
72 }
73
74 void TaskService::PostBoundDelayedTask(RunnerId runner,
75 base::OnceClosure task,
76 base::TimeDelta delay) {
77 base::AutoLock instance_lock(instance_lock_);
78 if (bound_instance_id_ == kInvalidInstanceId)
79 return;
80 base::AutoLock lock(lock_);
81 GetTaskRunner(runner)->PostDelayedTask(
82 FROM_HERE,
83 base::BindOnce(&TaskService::RunTask, base::Unretained(this),
84 bound_instance_id_, runner, std::move(task)),
85 delay);
86 }
87
88 void TaskService::PostBoundReplyTask(base::OnceClosure task) {
89 base::AutoLock instance_lock(instance_lock_);
90 if (bound_instance_id_ == kInvalidInstanceId)
91 return;
92 base::AutoLock lock(lock_);
93 DCHECK(reply_task_runner_);
94 reply_task_runner_->PostTask(
95 FROM_HERE,
96 base::BindOnce(&TaskService::RunTask, base::Unretained(this),
97 bound_instance_id_, kReplyRunnerId, std::move(task)));
98 }
99
100 scoped_refptr<base::SingleThreadTaskRunner> TaskService::GetTaskRunner(
101 RunnerId runner_id) {
102 lock_.AssertAcquired();
103 DCHECK_NE(runner_id, kReplyRunnerId);
104 DCHECK_EQ(threads_.size(), thread_task_locks_.size());
105 if (threads_.size() <= static_cast<size_t>(runner_id)) {
106 threads_.resize(runner_id + 1);
107 thread_task_locks_.resize(runner_id + 1);
108 }
109 if (!threads_[runner_id]) {
110 threads_[runner_id] = base::MakeUnique<base::Thread>(
111 base::StringPrintf("MidiService_TaskService_Thread(%d)", runner_id));
112 #if defined(OS_WIN)
113 threads_[runner_id]->init_com_with_mta(true);
114 #endif
115 threads_[runner_id]->Start();
116 DCHECK(!thread_task_locks_[runner_id]);
117 thread_task_locks_[runner_id] = base::MakeUnique<base::Lock>();
118 }
119 return threads_[runner_id]->task_runner();
120 }
121
122 void TaskService::RunTask(InstanceId instance_id,
123 RunnerId runner_id,
124 base::OnceClosure task) {
125 std::unique_ptr<base::AutoLock> task_lock;
126 {
127 base::AutoLock instance_lock(instance_lock_);
128 // If UnbindInstance() is already called, do nothing.
129 if (instance_id != bound_instance_id_)
130 return;
131
132 // Obtains task lock to ensure that the instance should not complete
133 // UnbindInstance() while running the |task|.
134 base::AutoLock lock(lock_);
135 task_lock = base::MakeUnique<base::AutoLock>(
136 (runner_id == kReplyRunnerId) ? reply_task_lock_
137 : *thread_task_locks_[runner_id]);
138 }
139 std::move(task).Run();
140 }
141
142 } // namespace midi
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698