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/message_loop/message_loop_proxy.h"
11 #include "base/task_runner.h"
12 #include "base/time/time.h"
14 using base::TaskRunner
;
16 namespace extensions
{
18 struct OneShotEvent::TaskInfo
{
20 TaskInfo(const tracked_objects::Location
& from_here
,
21 const scoped_refptr
<TaskRunner
>& runner
,
22 const base::Closure
& task
,
23 const base::TimeDelta
& delay
)
24 : from_here(from_here
), runner(runner
), task(task
), delay(delay
) {
25 CHECK(runner
.get()); // Detect mistakes with a decent stack frame.
27 tracked_objects::Location from_here
;
28 scoped_refptr
<TaskRunner
> runner
;
30 base::TimeDelta delay
;
33 OneShotEvent::OneShotEvent() : signaled_(false) {
34 // It's acceptable to construct the OneShotEvent on one thread, but
35 // immediately move it to another thread.
36 thread_checker_
.DetachFromThread();
38 OneShotEvent::OneShotEvent(bool signaled
) : signaled_(signaled
) {
39 thread_checker_
.DetachFromThread();
41 OneShotEvent::~OneShotEvent() {}
43 void OneShotEvent::Post(const tracked_objects::Location
& from_here
,
44 const base::Closure
& task
) const {
46 from_here
, task
, base::MessageLoopProxy::current(), base::TimeDelta());
49 void OneShotEvent::Post(const tracked_objects::Location
& from_here
,
50 const base::Closure
& task
,
51 const scoped_refptr
<TaskRunner
>& runner
) const {
52 PostImpl(from_here
, task
, runner
, base::TimeDelta());
55 void OneShotEvent::PostDelayed(const tracked_objects::Location
& from_here
,
56 const base::Closure
& task
,
57 const base::TimeDelta
& delay
) const {
58 PostImpl(from_here
, task
, base::MessageLoopProxy::current(), delay
);
61 void OneShotEvent::Signal() {
62 DCHECK(thread_checker_
.CalledOnValidThread());
64 CHECK(!signaled_
) << "Only call Signal once.";
67 // After this point, a call to Post() from one of the queued tasks
68 // could proceed immediately, but the fact that this object is
69 // single-threaded prevents that from being relevant.
71 // We could randomize tasks_ in debug mode in order to check that
72 // the order doesn't matter...
73 for (size_t i
= 0; i
< tasks_
.size(); ++i
) {
74 const TaskInfo
& task
= tasks_
[i
];
75 if (task
.delay
!= base::TimeDelta())
76 task
.runner
->PostDelayedTask(task
.from_here
, task
.task
, task
.delay
);
78 task
.runner
->PostTask(task
.from_here
, task
.task
);
82 void OneShotEvent::PostImpl(const tracked_objects::Location
& from_here
,
83 const base::Closure
& task
,
84 const scoped_refptr
<TaskRunner
>& runner
,
85 const base::TimeDelta
& delay
) const {
86 DCHECK(thread_checker_
.CalledOnValidThread());
89 if (delay
!= base::TimeDelta())
90 runner
->PostDelayedTask(from_here
, task
, delay
);
92 runner
->PostTask(from_here
, task
);
94 tasks_
.push_back(TaskInfo(from_here
, runner
, task
, delay
));
98 } // namespace extensions