f11d9ca2452dfd2126ddf73123239e0fb99ccb90
[folly.git] / folly / experimental / fibers / EventBaseLoopController.h
1 /*
2  * Copyright 2015 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 <memory>
19 #include <atomic>
20 #include <folly/experimental/fibers/LoopController.h>
21 #include <folly/io/async/EventBase.h>
22
23 namespace folly {
24 class EventBase;
25 }
26
27 namespace folly { namespace fibers {
28
29 class FiberManager;
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  private:
46   class ControllerCallback : public folly::EventBase::LoopCallback {
47    public:
48     explicit ControllerCallback(EventBaseLoopController& controller)
49         : controller_(controller) {}
50
51     void runLoopCallback() noexcept override { controller_.runLoop(); }
52
53    private:
54     EventBaseLoopController& controller_;
55   };
56
57   class DestructionCallback : public folly::EventBase::LoopCallback {
58    public:
59     DestructionCallback() : alive_(new int(42)) {}
60     ~DestructionCallback() { reset(); }
61
62     void runLoopCallback() noexcept override { reset(); }
63
64     std::weak_ptr<void> getWeak() { return {alive_}; }
65
66    private:
67     void reset() {
68       std::weak_ptr<void> aliveWeak(alive_);
69       alive_.reset();
70
71       while (!aliveWeak.expired()) {
72         // Spin until all operations requiring EventBaseLoopController to be
73         // alive are complete.
74       }
75     }
76
77     std::shared_ptr<void> alive_;
78   };
79
80   bool awaitingScheduling_{false};
81   folly::EventBase* eventBase_{nullptr};
82   ControllerCallback callback_;
83   DestructionCallback destructionCallback_;
84   FiberManager* fm_{nullptr};
85   std::atomic<bool> eventBaseAttached_{false};
86   std::weak_ptr<void> aliveWeak_;
87
88   /* LoopController interface */
89
90   void setFiberManager(FiberManager* fm) override;
91   void schedule() override;
92   void cancel() override;
93   void runLoop();
94   void scheduleThreadSafe(std::function<bool()> func) override;
95   void timedSchedule(std::function<void()> func, TimePoint time) override;
96
97   friend class FiberManager;
98 };
99
100 }}  // folly::fibers
101
102 #include "EventBaseLoopController-inl.h"