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

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

Issue 2741713002: Web MIDI: implement TaskService (Closed)
Patch Set: offline review: merge reply task to bound task 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
« no previous file with comments | « media/midi/task_service.h ('k') | media/midi/task_service_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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
16 } // namespace
17
18 TaskService::TaskService()
19 : next_instance_id_(0), bound_instance_id_(kInvalidInstanceId) {
20 thread_task_locks_.resize(1);
21 thread_task_locks_[0] = base::MakeUnique<base::Lock>();
22 }
23
24 TaskService::~TaskService() {
25 base::AutoLock lock(lock_);
26 threads_.clear();
27 }
28
29 bool TaskService::BindInstance() {
30 {
31 base::AutoLock instance_lock(instance_lock_);
32 if (bound_instance_id_ != kInvalidInstanceId)
33 return false;
34 bound_instance_id_ = next_instance_id_++;
35 }
36 base::AutoLock lock(lock_);
37 DCHECK(!reply_task_runner_);
38 reply_task_runner_ = base::ThreadTaskRunnerHandle::Get();
39 return true;
40 }
41
42 bool TaskService::UnbindInstance() {
43 {
44 base::AutoLock instance_lock(instance_lock_);
45 if (bound_instance_id_ == kInvalidInstanceId)
46 return false;
47 bound_instance_id_ = kInvalidInstanceId;
48 }
49 base::AutoLock lock(lock_);
50 DCHECK(reply_task_runner_);
51 reply_task_runner_ = nullptr;
52 // From now on RunTask will never run any task bound to the instance id.
53 // But invoked tasks might be still running here. To ensure no task run before
54 // quitting this method, take all |thread_task_locks_| once.
55 for (auto& task_lock : thread_task_locks_)
56 base::AutoLock auto_task_lock(*task_lock);
57 return true;
58 }
59
60 void TaskService::PostStaticTask(RunnerId runner_id, base::OnceClosure task) {
61 scoped_refptr<base::SingleThreadTaskRunner> runner;
62 {
63 base::AutoLock lock(lock_);
64 runner = GetTaskRunner(runner_id);
65 }
66 runner->PostTask(FROM_HERE, std::move(task));
67 }
68
69 void TaskService::PostBoundTask(RunnerId runner_id, base::OnceClosure task) {
70 base::AutoLock instance_lock(instance_lock_);
71 if (bound_instance_id_ == kInvalidInstanceId)
72 return;
73 scoped_refptr<base::SingleThreadTaskRunner> runner;
74 InstanceId instance_id;
75 {
76 base::AutoLock lock(lock_);
77 runner = GetTaskRunner(runner_id);
78 instance_id = bound_instance_id_;
79 }
80 runner->PostTask(FROM_HERE,
81 base::BindOnce(&TaskService::RunTask, base::Unretained(this),
82 instance_id, runner_id, std::move(task)));
83 }
84
85 void TaskService::PostBoundDelayedTask(RunnerId runner_id,
86 base::OnceClosure task,
87 base::TimeDelta delay) {
88 base::AutoLock instance_lock(instance_lock_);
89 if (bound_instance_id_ == kInvalidInstanceId)
90 return;
91 scoped_refptr<base::SingleThreadTaskRunner> runner;
92 InstanceId instance_id;
93 {
94 base::AutoLock lock(lock_);
95 runner = GetTaskRunner(runner_id);
96 instance_id = bound_instance_id_;
97 }
98 runner->PostDelayedTask(
99 FROM_HERE,
100 base::BindOnce(&TaskService::RunTask, base::Unretained(this), instance_id,
101 runner_id, std::move(task)),
102 delay);
103 }
104
105 scoped_refptr<base::SingleThreadTaskRunner> TaskService::GetTaskRunner(
106 RunnerId runner_id) {
107 lock_.AssertAcquired();
108 if (runner_id == kDefaultRunnerId)
109 return reply_task_runner_;
110
111 DCHECK_EQ(threads_.size() + 1u, thread_task_locks_.size());
yhirano 2017/06/12 07:54:44 You don't need this "+1". Just leaving threads_[0]
Takashi Toyoshima 2017/06/13 06:29:41 sounds a nice idea to keep the code simple. Done.
112 size_t thread_index = runner_id - 1;
113
114 if (threads_.size() <= thread_index) {
115 threads_.resize(thread_index + 1);
116 thread_task_locks_.resize(runner_id + 1);
117 }
118 if (!threads_[thread_index]) {
119 threads_[thread_index] = base::MakeUnique<base::Thread>(base::StringPrintf(
120 "MidiService_TaskService_Thread(%zu)", thread_index));
121 #if defined(OS_WIN)
122 threads_[thread_index]->init_com_with_mta(true);
123 #endif
124 threads_[thread_index]->Start();
125
126 DCHECK(!thread_task_locks_[runner_id]);
127 thread_task_locks_[runner_id] = base::MakeUnique<base::Lock>();
128 }
129 return threads_[thread_index]->task_runner();
130 }
131
132 void TaskService::RunTask(InstanceId instance_id,
133 RunnerId runner_id,
134 base::OnceClosure task) {
135 std::unique_ptr<base::AutoLock> task_lock;
136 {
137 base::AutoLock instance_lock(instance_lock_);
138 // If UnbindInstance() is already called, do nothing.
139 if (instance_id != bound_instance_id_)
140 return;
141
142 // Obtains task lock to ensure that the instance should not complete
143 // UnbindInstance() while running the |task|.
144 base::AutoLock lock(lock_);
145 task_lock =
146 base::MakeUnique<base::AutoLock>(*thread_task_locks_[runner_id]);
147 }
148 std::move(task).Run();
149 }
150
151 } // namespace midi
OLDNEW
« no previous file with comments | « media/midi/task_service.h ('k') | media/midi/task_service_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698