f389a45edfa992bcb7bc901455fe2cff18793a7f
[folly.git] / folly / fibers / EventBaseLoopController.h
1 /*
2  * Copyright 2017 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 #pragma once
17
18 #include <folly/fibers/FiberManagerInternal.h>
19 #include <folly/fibers/LoopController.h>
20 #include <folly/io/async/EventBase.h>
21 #include <folly/io/async/VirtualEventBase.h>
22 #include <atomic>
23 #include <memory>
24
25 namespace folly {
26 class EventBase;
27 }
28
29 namespace folly {
30 namespace fibers {
31
32 template <typename EventBaseT>
33 class EventBaseLoopControllerT : public LoopController {
34  public:
35   explicit EventBaseLoopControllerT();
36   ~EventBaseLoopControllerT();
37
38   /**
39    * Attach EventBase after LoopController was created.
40    */
41   void attachEventBase(EventBaseT& eventBase);
42
43   EventBaseT* getEventBase() {
44     return eventBase_;
45   }
46
47   void setLoopRunner(InlineFunctionRunner* loopRunner) {
48     loopRunner_ = loopRunner;
49   }
50
51  private:
52   class ControllerCallback : public folly::EventBase::LoopCallback {
53    public:
54     explicit ControllerCallback(EventBaseLoopControllerT& controller)
55         : controller_(controller) {}
56
57     void runLoopCallback() noexcept override {
58       controller_.runLoop();
59     }
60
61    private:
62     EventBaseLoopControllerT& controller_;
63   };
64
65   class DestructionCallback : public folly::EventBase::LoopCallback {
66    public:
67     DestructionCallback() : alive_(new int(42)) {}
68     ~DestructionCallback() {
69       reset();
70     }
71
72     void runLoopCallback() noexcept override {
73       reset();
74     }
75
76     std::weak_ptr<void> getWeak() {
77       return {alive_};
78     }
79
80    private:
81     void reset() {
82       std::weak_ptr<void> aliveWeak(alive_);
83       alive_.reset();
84
85       while (!aliveWeak.expired()) {
86         // Spin until all operations requiring EventBaseLoopController to be
87         // alive are complete.
88       }
89     }
90
91     std::shared_ptr<void> alive_;
92   };
93
94   bool awaitingScheduling_{false};
95   EventBaseT* eventBase_{nullptr};
96   Executor::KeepAlive eventBaseKeepAlive_;
97   ControllerCallback callback_;
98   DestructionCallback destructionCallback_;
99   FiberManager* fm_{nullptr};
100   std::atomic<bool> eventBaseAttached_{false};
101   std::weak_ptr<void> aliveWeak_;
102   InlineFunctionRunner* loopRunner_{nullptr};
103
104   /* LoopController interface */
105
106   void setFiberManager(FiberManager* fm) override;
107   void schedule() override;
108   void cancel() override;
109   void runLoop() override;
110   void scheduleThreadSafe(std::function<bool()> func) override;
111   void timedSchedule(std::function<void()> func, TimePoint time) override;
112
113   friend class FiberManager;
114 };
115
116 using EventBaseLoopController = EventBaseLoopControllerT<folly::EventBase>;
117 }
118 } // folly::fibers
119
120 #include "EventBaseLoopController-inl.h"