Consistency in namespace-closing comments
[folly.git] / folly / fibers / EventBaseLoopController-inl.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 #include <folly/Memory.h>
17 #include <folly/fibers/EventBaseLoopController.h>
18
19 namespace folly {
20 namespace fibers {
21
22 inline EventBaseLoopController::EventBaseLoopController()
23     : callback_(*this), aliveWeak_(destructionCallback_.getWeak()) {}
24
25 inline EventBaseLoopController::~EventBaseLoopController() {
26   callback_.cancelLoopCallback();
27   eventBaseKeepAlive_.reset();
28 }
29
30 inline void EventBaseLoopController::attachEventBase(EventBase& eventBase) {
31   attachEventBase(eventBase.getVirtualEventBase());
32 }
33
34 inline void EventBaseLoopController::attachEventBase(
35     VirtualEventBase& eventBase) {
36   if (eventBase_ != nullptr) {
37     LOG(ERROR) << "Attempt to reattach EventBase to LoopController";
38   }
39
40   eventBase_ = &eventBase;
41   eventBase_->runOnDestruction(&destructionCallback_);
42
43   eventBaseAttached_ = true;
44
45   if (awaitingScheduling_) {
46     schedule();
47   }
48 }
49
50 inline void EventBaseLoopController::setFiberManager(FiberManager* fm) {
51   fm_ = fm;
52 }
53
54 inline void EventBaseLoopController::schedule() {
55   if (eventBase_ == nullptr) {
56     // In this case we need to postpone scheduling.
57     awaitingScheduling_ = true;
58   } else {
59     // Schedule it to run in current iteration.
60
61     if (!eventBaseKeepAlive_) {
62       eventBaseKeepAlive_ = eventBase_->getKeepAliveToken();
63     }
64     eventBase_->getEventBase().runInLoop(&callback_, true);
65     awaitingScheduling_ = false;
66   }
67 }
68
69 inline void EventBaseLoopController::cancel() {
70   callback_.cancelLoopCallback();
71 }
72
73 inline void EventBaseLoopController::runLoop() {
74   if (!eventBaseKeepAlive_) {
75     // runLoop can be called twice if both schedule() and scheduleThreadSafe()
76     // were called.
77     if (!fm_->hasTasks()) {
78       return;
79     }
80     eventBaseKeepAlive_ = eventBase_->getKeepAliveToken();
81   }
82   if (loopRunner_) {
83     loopRunner_->run([&] { fm_->loopUntilNoReadyImpl(); });
84   } else {
85     fm_->loopUntilNoReadyImpl();
86   }
87   if (!fm_->hasTasks()) {
88     eventBaseKeepAlive_.reset();
89   }
90 }
91
92 inline void EventBaseLoopController::scheduleThreadSafe(
93     std::function<bool()> func) {
94   /* The only way we could end up here is if
95      1) Fiber thread creates a fiber that awaits (which means we must
96         have already attached, fiber thread wouldn't be running).
97      2) We move the promise to another thread (this move is a memory fence)
98      3) We fulfill the promise from the other thread. */
99   assert(eventBaseAttached_);
100
101   auto alive = aliveWeak_.lock();
102
103   if (func() && alive) {
104     auto aliveWeak = aliveWeak_;
105     eventBase_->runInEventBaseThread([this, aliveWeak]() {
106       if (!aliveWeak.expired()) {
107         runLoop();
108       }
109     });
110   }
111 }
112
113 inline void EventBaseLoopController::timedSchedule(
114     std::function<void()> func,
115     TimePoint time) {
116   assert(eventBaseAttached_);
117
118   // We want upper bound for the cast, thus we just add 1
119   auto delay_ms =
120       std::chrono::duration_cast<std::chrono::milliseconds>(time - Clock::now())
121           .count() +
122       1;
123   // If clock is not monotonic
124   delay_ms = std::max<decltype(delay_ms)>(delay_ms, 0);
125   eventBase_->tryRunAfterDelay(func, uint32_t(delay_ms));
126 }
127 } // namespace fibers
128 } // namespace folly