aboutsummaryrefslogtreecommitdiffhomepage
path: root/Firestore/core/src/firebase/firestore/util/executor.h
blob: df8b0b55ade330d5a1a9081d5fb9d12b23640b90 (plain)
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_