1/*
2 * Copyright 2014-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 <list>
20#include <set>
21
22#include <folly/ThreadLocal.h>
23#include <folly/io/async/EventBase.h>
24
25namespace folly {
26
27/**
28 * Manager for per-thread EventBase objects.
29 * This class will find or create a EventBase for the current
30 * thread, associated with thread-specific storage for that thread.
31 * Although a typical application will generally only have one
32 * EventBaseManager, there is no restriction on multiple instances;
33 * the EventBases belong to one instance are isolated from those of
34 * another.
35 */
36class EventBaseManager {
37 public:
38 // XXX Constructing a EventBaseManager directly is DEPRECATED and not
39 // encouraged. You should instead use the global singleton if possible.
40 EventBaseManager() {}
41
42 ~EventBaseManager() {}
43
44 explicit EventBaseManager(const std::shared_ptr<EventBaseObserver>& observer)
45 : observer_(observer) {}
46
47 /**
48 * Get the global EventBaseManager for this program. Ideally all users
49 * of EventBaseManager go through this interface and do not construct
50 * EventBaseManager directly.
51 */
52 static EventBaseManager* get();
53
54 /**
55 * Get the EventBase for this thread, or create one if none exists yet.
56 *
57 * If no EventBase exists for this thread yet, a new one will be created and
58 * returned. May throw std::bad_alloc if allocation fails.
59 */
60 EventBase* getEventBase() const;
61
62 /**
63 * Get the EventBase for this thread.
64 *
65 * Returns nullptr if no EventBase has been created for this thread yet.
66 */
67 EventBase* getExistingEventBase() const {
68 EventBaseInfo* info = localStore_.get();
69 if (info == nullptr) {
70 return nullptr;
71 }
72 return info->eventBase;
73 }
74
75 /**
76 * Set the EventBase to be used by this thread.
77 *
78 * This may only be called if no EventBase has been defined for this thread
79 * yet. If a EventBase is already defined for this thread, a
80 * std::runtime_error is thrown. std::bad_alloc may also be thrown if
81 * allocation fails while setting the EventBase.
82 *
83 * This should typically be invoked by the code that will call loop() on the
84 * EventBase, to make sure the EventBaseManager points to the correct
85 * EventBase that is actually running in this thread.
86 */
87 void setEventBase(EventBase* eventBase, bool takeOwnership);
88
89 /**
90 * Clear the EventBase for this thread.
91 *
92 * This can be used if the code driving the EventBase loop() has finished
93 * the loop and new events should no longer be added to the EventBase.
94 */
95 void clearEventBase();
96
97 /**
98 * Gives the caller all references to all assigned EventBase instances at
99 * this moment in time. Locks a mutex so that these EventBase set cannot
100 * be changed, and also the caller can rely on no instances being destructed.
101 */
102 template <typename FunctionType>
103 void withEventBaseSet(const FunctionType& runnable) {
104 // grab the mutex for the caller
105 std::lock_guard<std::mutex> g(*&eventBaseSetMutex_);
106 // give them only a const set to work with
107 const std::set<EventBase*>& constSet = eventBaseSet_;
108 runnable(constSet);
109 }
110
111 private:
112 struct EventBaseInfo {
113 EventBaseInfo(EventBase* evb, bool owned) : eventBase(evb), owned_(owned) {}
114
115 EventBaseInfo() : eventBase(new EventBase), owned_(true) {}
116
117 EventBase* eventBase;
118 bool owned_;
119 ~EventBaseInfo() {
120 if (owned_) {
121 delete eventBase;
122 }
123 }
124 };
125
126 // Forbidden copy constructor and assignment opererator
127 EventBaseManager(EventBaseManager const&);
128 EventBaseManager& operator=(EventBaseManager const&);
129
130 void trackEventBase(EventBase* evb) {
131 std::lock_guard<std::mutex> g(*&eventBaseSetMutex_);
132 eventBaseSet_.insert(evb);
133 }
134
135 void untrackEventBase(EventBase* evb) {
136 std::lock_guard<std::mutex> g(*&eventBaseSetMutex_);
137 eventBaseSet_.erase(evb);
138 }
139
140 mutable folly::ThreadLocalPtr<EventBaseInfo> localStore_;
141
142 // set of "active" EventBase instances
143 // (also see the mutex "eventBaseSetMutex_" below
144 // which governs access to this).
145 mutable std::set<EventBase*> eventBaseSet_;
146
147 // a mutex to use as a guard for the above set
148 std::mutex eventBaseSetMutex_;
149
150 std::shared_ptr<folly::EventBaseObserver> observer_;
151};
152
153} // namespace folly
154