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
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
|
/*
* Copyright 2018 Google
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef FIRESTORE_CORE_SRC_FIREBASE_FIRESTORE_UTIL_EXECUTOR_H_
#define FIRESTORE_CORE_SRC_FIREBASE_FIRESTORE_UTIL_EXECUTOR_H_
#include <chrono> // NOLINT(build/c++11)
#include <functional>
#include <string>
#include <utility>
#include "absl/types/optional.h"
namespace firebase {
namespace firestore {
namespace util {
// A handle to an operation scheduled for future execution. The handle may
// outlive the operation, but it *cannot* outlive the executor that created it.
class DelayedOperation {
public:
DelayedOperation() {
}
// If the operation has not been run yet, cancels the operation. Otherwise,
// this function is a no-op.
void Cancel() {
cancel_func_();
}
// Internal use only.
explicit DelayedOperation(std::function<void()>&& cancel_func)
: cancel_func_{std::move(cancel_func)} {
}
private:
std::function<void()> cancel_func_;
};
namespace internal {
// An interface to a platform-specific executor of asynchronous operations
// (called tasks on other platforms).
//
// Operations may be scheduled for immediate or delayed execution. Operations
// delayed until the exact same time are scheduled in FIFO order.
//
// The operations are executed sequentially; only a single operation is executed
// at any given time.
//
// Delayed operations may be canceled if they have not already been run.
class Executor {
public:
using Tag = int;
using Operation = std::function<void()>;
using Milliseconds = std::chrono::milliseconds;
// Operations scheduled for future execution have an opaque tag. The value of
// the tag is ignored by the executor but can be used to find operations with
// a given tag after they are scheduled.
struct TaggedOperation {
TaggedOperation() {
}
TaggedOperation(const Tag tag, Operation&& operation)
: tag{tag}, operation{std::move(operation)} {
}
Tag tag = 0;
Operation operation;
};
virtual ~Executor() {
}
// Schedules the `operation` to be asynchronously executed as soon as
// possible, in FIFO order.
virtual void Execute(Operation&& operation) = 0;
// Like `Execute`, but blocks until the `operation` finishes, consequently
// draining immediate operations from the executor.
virtual void ExecuteBlocking(Operation&& operation) = 0;
// Scheduled the given `operation` to be executed after `delay` milliseconds
// from now, and returns a handle that allows to cancel the operation
// (provided it hasn't been run already). The operation is tagged to allow
// retrieving it later.
//
// `delay` must be non-negative; use `Execute` to schedule operations for
// immediate execution.
virtual DelayedOperation Schedule(Milliseconds delay,
TaggedOperation&& operation) = 0;
// Checks for the caller whether it is being invoked by this executor.
virtual bool IsCurrentExecutor() const = 0;
// Returns some sort of an identifier for the current execution context. The
// only guarantee is that it will return different values depending on whether
// this function is invoked by this executor or not.
virtual std::string CurrentExecutorName() const = 0;
// Like `CurrentExecutorName`, but returns an identifier for this executor,
// whether the caller code currently runs on this executor or not.
virtual std::string Name() const = 0;
// Checks whether an operation tagged with the given `tag` is currently
// scheduled for future execution.
virtual bool IsScheduled(Tag tag) const = 0;
// Removes the nearest due scheduled operation from the schedule and returns
// it to the caller. This function may be used to reschedule operations.
// Immediate operations don't count; only operations scheduled for delayed
// execution may be removed. If no such operations are currently scheduled, an
// empty `optional` is returned.
virtual absl::optional<TaggedOperation> PopFromSchedule() = 0;
};
} // namespace internal
} // namespace util
} // namespace firestore
} // namespace firebase
#endif // FIRESTORE_CORE_SRC_FIREBASE_FIRESTORE_UTIL_EXECUTOR_H_
|