1 // Copyright 2013 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.
5 #include "extensions/common/one_shot_event.h"
7 #include "base/callback.h"
8 #include "base/lazy_instance.h"
9 #include "base/location.h"
10 #include "base/single_thread_task_runner.h"
11 #include "base/task_runner.h"
12 #include "base/thread_task_runner_handle.h"
13 #include "base/time/time.h"
15 using base::SingleThreadTaskRunner
;
17 namespace extensions
{
19 struct OneShotEvent::TaskInfo
{
21 TaskInfo(const tracked_objects::Location
& from_here
,
22 const scoped_refptr
<SingleThreadTaskRunner
>& runner
,
23 const base::Closure
& task
,
24 const base::TimeDelta
& delay
)
25 : from_here(from_here
), runner(runner
), task(task
), delay(delay
) {
26 CHECK(runner
.get()); // Detect mistakes with a decent stack frame.
28 tracked_objects::Location from_here
;
29 scoped_refptr
<SingleThreadTaskRunner
> runner
;
31 base::TimeDelta delay
;
34 OneShotEvent::OneShotEvent() : signaled_(false) {
35 // It's acceptable to construct the OneShotEvent on one thread, but
36 // immediately move it to another thread.
37 thread_checker_
.DetachFromThread();
39 OneShotEvent::OneShotEvent(bool signaled
) : signaled_(signaled
) {
40 thread_checker_
.DetachFromThread();
42 OneShotEvent::~OneShotEvent() {}
44 void OneShotEvent::Post(const tracked_objects::Location
& from_here
,
45 const base::Closure
& task
) const {
46 PostImpl(from_here
, task
, base::ThreadTaskRunnerHandle::Get(),
50 void OneShotEvent::Post(
51 const tracked_objects::Location
& from_here
,
52 const base::Closure
& task
,
53 const scoped_refptr
<SingleThreadTaskRunner
>& runner
) const {
54 PostImpl(from_here
, task
, runner
, base::TimeDelta());
57 void OneShotEvent::PostDelayed(const tracked_objects::Location
& from_here
,
58 const base::Closure
& task
,
59 const base::TimeDelta
& delay
) const {
60 PostImpl(from_here
, task
, base::ThreadTaskRunnerHandle::Get(), delay
);
63 void OneShotEvent::Signal() {
64 DCHECK(thread_checker_
.CalledOnValidThread());
66 CHECK(!signaled_
) << "Only call Signal once.";
69 // After this point, a call to Post() from one of the queued tasks
70 // could proceed immediately, but the fact that this object is
71 // single-threaded prevents that from being relevant.
73 // We could randomize tasks_ in debug mode in order to check that
74 // the order doesn't matter...
75 for (size_t i
= 0; i
< tasks_
.size(); ++i
) {
76 const TaskInfo
& task
= tasks_
[i
];
77 if (task
.delay
!= base::TimeDelta())
78 task
.runner
->PostDelayedTask(task
.from_here
, task
.task
, task
.delay
);
80 task
.runner
->PostTask(task
.from_here
, task
.task
);
84 void OneShotEvent::PostImpl(const tracked_objects::Location
& from_here
,
85 const base::Closure
& task
,
86 const scoped_refptr
<SingleThreadTaskRunner
>& runner
,
87 const base::TimeDelta
& delay
) const {
88 DCHECK(thread_checker_
.CalledOnValidThread());
91 if (delay
!= base::TimeDelta())
92 runner
->PostDelayedTask(from_here
, task
, delay
);
94 runner
->PostTask(from_here
, task
);
96 tasks_
.push_back(TaskInfo(from_here
, runner
, task
, delay
));
100 } // namespace extensions