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