2 * Copyright 2014 Facebook, Inc.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
18 #include <folly/wangle/Executor.h>
19 #include <semaphore.h>
25 namespace folly { namespace wangle {
26 /// A ManualExecutor only does work when you turn the crank, by calling
27 /// run() or indirectly with makeProgress() or waitFor().
29 /// The clock for a manual executor starts at 0 and advances only when you
30 /// ask it to. i.e. time is also under manual control.
32 /// NB No attempt has been made to make anything other than add and schedule
34 class ManualExecutor : public Executor {
38 void add(Action&&) override;
40 /// Do work. Returns the number of actions that were executed (maybe 0).
41 /// Non-blocking, in the sense that we don't wait for work (we can't
42 /// control whether one of the actions blocks).
43 /// This is stable, it will not chase an ever-increasing tail of work.
44 /// This also means, there may be more work available to perform at the
45 /// moment that this returns.
48 /// Wait for work to do.
51 /// Wait for work to do, and do it.
57 /// makeProgress until this Future is ready.
58 template <class F> void waitFor(F const& f) {
63 virtual void scheduleAt(Action&& a, TimePoint const& t) override {
64 std::lock_guard<std::mutex> lock(lock_);
65 scheduledActions_.emplace(t, std::move(a));
69 /// Advance the clock. The clock never advances on its own.
70 /// Advancing the clock causes some work to be done, if work is available
71 /// to do (perhaps newly available because of the advanced clock).
72 /// If dur is <= 0 this is a noop.
73 void advance(Duration const& dur) {
74 advanceTo(now_ + dur);
77 /// Advance the clock to this absolute time. If t is <= now(),
79 void advanceTo(TimePoint const& t);
81 TimePoint now() override { return now_; }
85 std::queue<Action> actions_;
88 // helper class to enable ordering of scheduled events in the priority
90 struct ScheduledAction {
95 ScheduledAction(TimePoint const& t, Action&& a)
96 : time(t), action(std::move(a))
98 static size_t seq = 0;
102 bool operator<(ScheduledAction const& b) const {
104 return ordinal < b.ordinal;
105 return time < b.time;
108 std::priority_queue<ScheduledAction> scheduledActions_;
109 TimePoint now_ = now_.min();