1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
|
// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef EXTENSIONS_COMMON_ONE_SHOT_EVENT_H_
#define EXTENSIONS_COMMON_ONE_SHOT_EVENT_H_
#include <vector>
#include "base/callback_forward.h"
#include "base/logging.h"
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
#include "base/threading/thread_checker.h"
namespace base {
class SingleThreadTaskRunner;
class TimeDelta;
}
namespace tracked_objects {
class Location;
}
namespace extensions {
// This class represents an event that's expected to happen once. It
// allows clients to guarantee that code is run after the OneShotEvent
// is signaled. If the OneShotEvent is destroyed before it's
// signaled, the delayed closures are destroyed without being run.
//
// This class is similar to a WaitableEvent combined with several
// WaitableEventWatchers, but using it is simpler.
//
// This class is not thread-safe, and must be used from a single thread.
class OneShotEvent {
public:
OneShotEvent();
// Use the following constructor to create an already signaled event. This is
// useful if you construct the event on a different thread from where it is
// used, in which case it is not possible to call Signal() just after
// construction.
explicit OneShotEvent(bool signaled);
~OneShotEvent();
// True if Signal has been called. This function is mostly for
// migrating old code; usually calling Post() unconditionally will
// result in more readable code.
bool is_signaled() const {
DCHECK(thread_checker_.CalledOnValidThread());
return signaled_;
}
// Causes is_signaled() to return true and all queued tasks to be
// run in an arbitrary order. This method must only be called once.
void Signal();
// Scheduled |task| to be called on |runner| after is_signaled()
// becomes true. If called with |delay|, then the task will happen
// (roughly) |delay| after is_signaled(), *not* |delay| after the
// post. Inside |task|, if this OneShotEvent is still alive,
// CHECK(is_signaled()) will never fail (which implies that
// OneShotEvent::Reset() doesn't exist).
//
// If |*this| is destroyed before being released, none of these
// tasks will be executed.
//
// Omitting the |runner| argument indicates that |task| should run
// on current thread's TaskRunner.
//
// Tasks may be run in an arbitrary order, not just FIFO. Tasks
// will never be called on the current thread before this function
// returns. Beware that there's no simple way to wait for all tasks
// on a OneShotEvent to complete, so it's almost never safe to use
// base::Unretained() when creating one.
//
// Const because Post() doesn't modify the logical state of this
// object (which is just the is_signaled() bit).
void Post(const tracked_objects::Location& from_here,
const base::Closure& task) const;
void Post(const tracked_objects::Location& from_here,
const base::Closure& task,
const scoped_refptr<base::SingleThreadTaskRunner>& runner) const;
void PostDelayed(const tracked_objects::Location& from_here,
const base::Closure& task,
const base::TimeDelta& delay) const;
private:
struct TaskInfo;
void PostImpl(const tracked_objects::Location& from_here,
const base::Closure& task,
const scoped_refptr<base::SingleThreadTaskRunner>& runner,
const base::TimeDelta& delay) const;
base::ThreadChecker thread_checker_;
bool signaled_;
// The task list is mutable because it's not part of the logical
// state of the object. This lets us return const references to the
// OneShotEvent to clients that just want to run tasks through it
// without worrying that they'll signal the event.
//
// Optimization note: We could reduce the size of this class to a
// single pointer by storing |signaled_| in the low bit of a
// pointer, and storing the size and capacity of the array (if any)
// on the far end of the pointer.
mutable std::vector<TaskInfo> tasks_;
};
} // namespace extensions
#endif // EXTENSIONS_COMMON_ONE_SHOT_EVENT_H_
|