1/*
2 * Copyright 2018-present Facebook, Inc.
3 *
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
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
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.
15 */
16
17#pragma once
18
19#include <glog/logging.h>
20#include <atomic>
21
22#include <folly/executors/ScheduledExecutor.h>
23#include <folly/futures/Future.h>
24
25namespace folly {
26
27struct FOLLY_EXPORT TimekeeperScheduledExecutorNoTimekeeper
28 : public std::logic_error {
29 TimekeeperScheduledExecutorNoTimekeeper()
30 : std::logic_error("No Timekeeper available") {}
31};
32
33// This class turns a Executor into a ScheduledExecutor.
34class TimekeeperScheduledExecutor : public ScheduledExecutor {
35 public:
36 TimekeeperScheduledExecutor(TimekeeperScheduledExecutor const&) = delete;
37 TimekeeperScheduledExecutor& operator=(TimekeeperScheduledExecutor const&) =
38 delete;
39 TimekeeperScheduledExecutor(TimekeeperScheduledExecutor&&) = delete;
40 TimekeeperScheduledExecutor& operator=(TimekeeperScheduledExecutor&&) =
41 delete;
42
43 static Executor::KeepAlive<TimekeeperScheduledExecutor> create(
44 Executor::KeepAlive<> parent,
45 Function<std::shared_ptr<Timekeeper>()> getTimekeeper =
46 detail::getTimekeeperSingleton);
47
48 virtual void add(Func func) override;
49
50 virtual void scheduleAt(Func&& func, ScheduledExecutor::TimePoint const& t)
51 override;
52
53 protected:
54 bool keepAliveAcquire() override;
55 void keepAliveRelease() override;
56
57 private:
58 TimekeeperScheduledExecutor(
59 KeepAlive<Executor>&& parent,
60 Function<std::shared_ptr<Timekeeper>()> getTimekeeper)
61 : parent_(std::move(parent)), getTimekeeper_(std::move(getTimekeeper)) {}
62
63 ~TimekeeperScheduledExecutor() {
64 DCHECK(!keepAliveCounter_);
65 }
66
67 void run(Func);
68
69 KeepAlive<Executor> parent_;
70 Function<std::shared_ptr<Timekeeper>()> getTimekeeper_;
71 std::atomic<ssize_t> keepAliveCounter_{1};
72};
73
74} // namespace folly
75