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