2 * Copyright 2017 Facebook, Inc.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
22 #include <folly/ThreadLocal.h>
23 #include <folly/io/async/EventBase.h>
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
36 class EventBaseManager {
38 // XXX Constructing a EventBaseManager directly is DEPRECATED and not
39 // encouraged. You should instead use the global singleton if possible.
46 explicit EventBaseManager(
47 const std::shared_ptr<EventBaseObserver>& observer
48 ) : observer_(observer) {}
51 * Get the global EventBaseManager for this program. Ideally all users
52 * of EventBaseManager go through this interface and do not construct
53 * EventBaseManager directly.
55 static EventBaseManager* get();
58 * Get the EventBase for this thread, or create one if none exists yet.
60 * If no EventBase exists for this thread yet, a new one will be created and
61 * returned. May throw std::bad_alloc if allocation fails.
63 EventBase* getEventBase() const;
66 * Get the EventBase for this thread.
68 * Returns nullptr if no EventBase has been created for this thread yet.
70 EventBase* getExistingEventBase() const {
71 EventBaseInfo* info = localStore_.get();
72 if (info == nullptr) {
75 return info->eventBase;
79 * Set the EventBase to be used by this thread.
81 * This may only be called if no EventBase has been defined for this thread
82 * yet. If a EventBase is already defined for this thread, a
83 * std::runtime_error is thrown. std::bad_alloc may also be thrown if
84 * allocation fails while setting the EventBase.
86 * This should typically be invoked by the code that will call loop() on the
87 * EventBase, to make sure the EventBaseManager points to the correct
88 * EventBase that is actually running in this thread.
90 void setEventBase(EventBase *eventBase, bool takeOwnership);
93 * Clear the EventBase for this thread.
95 * This can be used if the code driving the EventBase loop() has finished
96 * the loop and new events should no longer be added to the EventBase.
98 void clearEventBase();
101 * Gives the caller all references to all assigned EventBase instances at
102 * this moment in time. Locks a mutex so that these EventBase set cannot
103 * be changed, and also the caller can rely on no instances being destructed.
105 template <typename FunctionType>
106 void withEventBaseSet(const FunctionType& runnable) {
107 // grab the mutex for the caller
108 std::lock_guard<std::mutex> g(*&eventBaseSetMutex_);
109 // give them only a const set to work with
110 const std::set<EventBase *>& constSet = eventBaseSet_;
116 struct EventBaseInfo {
117 EventBaseInfo(EventBase *evb, bool owned)
122 : eventBase(new EventBase)
125 EventBase *eventBase;
134 // Forbidden copy constructor and assignment opererator
135 EventBaseManager(EventBaseManager const &);
136 EventBaseManager& operator=(EventBaseManager const &);
138 void trackEventBase(EventBase *evb) {
139 std::lock_guard<std::mutex> g(*&eventBaseSetMutex_);
140 eventBaseSet_.insert(evb);
143 void untrackEventBase(EventBase *evb) {
144 std::lock_guard<std::mutex> g(*&eventBaseSetMutex_);
145 eventBaseSet_.erase(evb);
148 mutable folly::ThreadLocalPtr<EventBaseInfo> localStore_;
150 // set of "active" EventBase instances
151 // (also see the mutex "eventBaseSetMutex_" below
152 // which governs access to this).
153 mutable std::set<EventBase *> eventBaseSet_;
155 // a mutex to use as a guard for the above set
156 std::mutex eventBaseSetMutex_;
158 std::shared_ptr<folly::EventBaseObserver> observer_;