Consistency in namespace-closing comments
[folly.git] / folly / io / async / EventBaseManager.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
17 #pragma once
18
19 #include <list>
20 #include <set>
21
22 #include <folly/ThreadLocal.h>
23 #include <folly/io/async/EventBase.h>
24
25 namespace 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  */
36 class 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
43   ~EventBaseManager() {
44   }
45
46   explicit EventBaseManager(
47     const std::shared_ptr<EventBaseObserver>& observer
48   ) : observer_(observer) {}
49
50   /**
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.
54    */
55   static EventBaseManager* get();
56
57   /**
58    * Get the EventBase for this thread, or create one if none exists yet.
59    *
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.
62    */
63   EventBase* getEventBase() const;
64
65   /**
66    * Get the EventBase for this thread.
67    *
68    * Returns nullptr if no EventBase has been created for this thread yet.
69    */
70   EventBase* getExistingEventBase() const {
71     EventBaseInfo* info = localStore_.get();
72     if (info == nullptr) {
73       return nullptr;
74     }
75     return info->eventBase;
76   }
77
78   /**
79    * Set the EventBase to be used by this thread.
80    *
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.
85    *
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.
89    */
90   void setEventBase(EventBase *eventBase, bool takeOwnership);
91
92   /**
93    * Clear the EventBase for this thread.
94    *
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.
97    */
98   void clearEventBase();
99
100   /**
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.
104    */
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_;
111     runnable(constSet);
112   }
113
114
115  private:
116   struct EventBaseInfo {
117     EventBaseInfo(EventBase *evb, bool owned)
118       : eventBase(evb),
119         owned_(owned) {}
120
121     EventBaseInfo()
122         : eventBase(new EventBase)
123         , owned_(true) {}
124
125     EventBase *eventBase;
126     bool owned_;
127     ~EventBaseInfo() {
128       if (owned_) {
129         delete eventBase;
130       }
131     }
132   };
133
134   // Forbidden copy constructor and assignment opererator
135   EventBaseManager(EventBaseManager const &);
136   EventBaseManager& operator=(EventBaseManager const &);
137
138   void trackEventBase(EventBase *evb) {
139     std::lock_guard<std::mutex> g(*&eventBaseSetMutex_);
140     eventBaseSet_.insert(evb);
141   }
142
143   void untrackEventBase(EventBase *evb) {
144     std::lock_guard<std::mutex> g(*&eventBaseSetMutex_);
145     eventBaseSet_.erase(evb);
146   }
147
148   mutable folly::ThreadLocalPtr<EventBaseInfo> localStore_;
149
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_;
154
155   // a mutex to use as a guard for the above set
156   std::mutex eventBaseSetMutex_;
157
158   std::shared_ptr<folly::EventBaseObserver> observer_;
159 };
160
161 } // namespace folly