Fix RequestContext held too long issue in EventBase
[folly.git] / folly / io / async / EventBase.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 <atomic>
20 #include <cerrno>
21 #include <cmath>
22 #include <cstdlib>
23 #include <functional>
24 #include <list>
25 #include <memory>
26 #include <mutex>
27 #include <queue>
28 #include <set>
29 #include <stack>
30 #include <unordered_map>
31 #include <unordered_set>
32 #include <utility>
33
34 #include <boost/intrusive/list.hpp>
35 #include <boost/utility.hpp>
36 #include <glog/logging.h>
37
38 #include <folly/Executor.h>
39 #include <folly/Function.h>
40 #include <folly/Portability.h>
41 #include <folly/ScopeGuard.h>
42 #include <folly/executors/DrivableExecutor.h>
43 #include <folly/experimental/ExecutionObserver.h>
44 #include <folly/io/async/AsyncTimeout.h>
45 #include <folly/io/async/HHWheelTimer.h>
46 #include <folly/io/async/Request.h>
47 #include <folly/io/async/TimeoutManager.h>
48 #include <folly/portability/Event.h>
49 #include <folly/synchronization/CallOnce.h>
50
51 namespace folly {
52
53 using Cob = Func; // defined in folly/Executor.h
54 template <typename MessageT>
55 class NotificationQueue;
56
57 namespace detail {
58 class EventBaseLocalBase;
59
60 class EventBaseLocalBaseBase {
61  public:
62   virtual void onEventBaseDestruction(EventBase& evb) = 0;
63   virtual ~EventBaseLocalBaseBase() = default;
64 };
65 } // namespace detail
66 template <typename T>
67 class EventBaseLocal;
68
69 class EventBaseObserver {
70  public:
71   virtual ~EventBaseObserver() = default;
72
73   virtual uint32_t getSampleRate() const = 0;
74
75   virtual void loopSample(
76     int64_t busyTime, int64_t idleTime) = 0;
77 };
78
79 // Helper class that sets and retrieves the EventBase associated with a given
80 // request via RequestContext. See Request.h for that mechanism.
81 class RequestEventBase : public RequestData {
82  public:
83   static EventBase* get() {
84     auto data = dynamic_cast<RequestEventBase*>(
85         RequestContext::get()->getContextData(kContextDataName));
86     if (!data) {
87       return nullptr;
88     }
89     return data->eb_;
90   }
91
92   static void set(EventBase* eb) {
93     RequestContext::get()->setContextData(
94         kContextDataName,
95         std::unique_ptr<RequestEventBase>(new RequestEventBase(eb)));
96   }
97
98   bool hasCallback() override {
99     return false;
100   }
101
102  private:
103   explicit RequestEventBase(EventBase* eb) : eb_(eb) {}
104   EventBase* eb_;
105   static constexpr const char* kContextDataName{"EventBase"};
106 };
107
108 class VirtualEventBase;
109
110 /**
111  * This class is a wrapper for all asynchronous I/O processing functionality
112  *
113  * EventBase provides a main loop that notifies EventHandler callback objects
114  * when I/O is ready on a file descriptor, and notifies AsyncTimeout objects
115  * when a specified timeout has expired.  More complex, higher-level callback
116  * mechanisms can then be built on top of EventHandler and AsyncTimeout.
117  *
118  * A EventBase object can only drive an event loop for a single thread.  To
119  * take advantage of multiple CPU cores, most asynchronous I/O servers have one
120  * thread per CPU, and use a separate EventBase for each thread.
121  *
122  * In general, most EventBase methods may only be called from the thread
123  * running the EventBase's loop.  There are a few exceptions to this rule, for
124  * methods that are explicitly intended to allow communication with a
125  * EventBase from other threads.  When it is safe to call a method from
126  * another thread it is explicitly listed in the method comments.
127  */
128 class EventBase : private boost::noncopyable,
129                   public TimeoutManager,
130                   public DrivableExecutor {
131  public:
132   using Func = folly::Function<void()>;
133
134   /**
135    * A callback interface to use with runInLoop()
136    *
137    * Derive from this class if you need to delay some code execution until the
138    * next iteration of the event loop.  This allows you to schedule code to be
139    * invoked from the top-level of the loop, after your immediate callers have
140    * returned.
141    *
142    * If a LoopCallback object is destroyed while it is scheduled to be run in
143    * the next loop iteration, it will automatically be cancelled.
144    */
145   class LoopCallback
146       : public boost::intrusive::list_base_hook<
147             boost::intrusive::link_mode<boost::intrusive::auto_unlink>> {
148    public:
149     virtual ~LoopCallback() = default;
150
151     virtual void runLoopCallback() noexcept = 0;
152     void cancelLoopCallback() {
153       context_.reset();
154       unlink();
155     }
156
157     bool isLoopCallbackScheduled() const {
158       return is_linked();
159     }
160
161    private:
162     typedef boost::intrusive::list<
163       LoopCallback,
164       boost::intrusive::constant_time_size<false> > List;
165
166     // EventBase needs access to LoopCallbackList (and therefore to hook_)
167     friend class EventBase;
168     friend class VirtualEventBase;
169     std::shared_ptr<RequestContext> context_;
170   };
171
172   class FunctionLoopCallback : public LoopCallback {
173    public:
174     explicit FunctionLoopCallback(Func&& function)
175         : function_(std::move(function)) {}
176
177     void runLoopCallback() noexcept override {
178       function_();
179       delete this;
180     }
181
182    private:
183     Func function_;
184   };
185
186   // Like FunctionLoopCallback, but saves one allocation. Use with caution.
187   //
188   // The caller is responsible for maintaining the lifetime of this callback
189   // until after the point at which the contained function is called.
190   class StackFunctionLoopCallback : public LoopCallback {
191    public:
192     explicit StackFunctionLoopCallback(Func&& function)
193         : function_(std::move(function)) {}
194     void runLoopCallback() noexcept override {
195       Func(std::move(function_))();
196     }
197
198    private:
199     Func function_;
200   };
201
202   /**
203    * Create a new EventBase object.
204    *
205    * @param enableTimeMeasurement Informs whether this event base should measure
206    *                              time. Disabling it would likely improve
207    *                              performance, but will disable some features
208    *                              that relies on time-measurement, including:
209    *                              observer, max latency and avg loop time.
210    */
211   explicit EventBase(bool enableTimeMeasurement = true);
212
213   /**
214    * Create a new EventBase object that will use the specified libevent
215    * event_base object to drive the event loop.
216    *
217    * The EventBase will take ownership of this event_base, and will call
218    * event_base_free(evb) when the EventBase is destroyed.
219    *
220    * @param enableTimeMeasurement Informs whether this event base should measure
221    *                              time. Disabling it would likely improve
222    *                              performance, but will disable some features
223    *                              that relies on time-measurement, including:
224    *                              observer, max latency and avg loop time.
225    */
226   explicit EventBase(event_base* evb, bool enableTimeMeasurement = true);
227   ~EventBase() override;
228
229   /**
230    * Runs the event loop.
231    *
232    * loop() will loop waiting for I/O or timeouts and invoking EventHandler
233    * and AsyncTimeout callbacks as their events become ready.  loop() will
234    * only return when there are no more events remaining to process, or after
235    * terminateLoopSoon() has been called.
236    *
237    * loop() may be called again to restart event processing after a previous
238    * call to loop() or loopForever() has returned.
239    *
240    * Returns true if the loop completed normally (if it processed all
241    * outstanding requests, or if terminateLoopSoon() was called).  If an error
242    * occurs waiting for events, false will be returned.
243    */
244   bool loop();
245
246   /**
247    * Wait for some events to become active, run them, then return.
248    *
249    * When EVLOOP_NONBLOCK is set in flags, the loop won't block if there
250    * are not any events to process.
251    *
252    * This is useful for callers that want to run the loop manually.
253    *
254    * Returns the same result as loop().
255    */
256   bool loopOnce(int flags = 0);
257
258   /**
259    * Runs the event loop.
260    *
261    * loopForever() behaves like loop(), except that it keeps running even if
262    * when there are no more user-supplied EventHandlers or AsyncTimeouts
263    * registered.  It will only return after terminateLoopSoon() has been
264    * called.
265    *
266    * This is useful for callers that want to wait for other threads to call
267    * runInEventBaseThread(), even when there are no other scheduled events.
268    *
269    * loopForever() may be called again to restart event processing after a
270    * previous call to loop() or loopForever() has returned.
271    *
272    * Throws a std::system_error if an error occurs.
273    */
274   void loopForever();
275
276   /**
277    * Causes the event loop to exit soon.
278    *
279    * This will cause an existing call to loop() or loopForever() to stop event
280    * processing and return, even if there are still events remaining to be
281    * processed.
282    *
283    * It is safe to call terminateLoopSoon() from another thread to cause loop()
284    * to wake up and return in the EventBase loop thread.  terminateLoopSoon()
285    * may also be called from the loop thread itself (for example, a
286    * EventHandler or AsyncTimeout callback may call terminateLoopSoon() to
287    * cause the loop to exit after the callback returns.)  If the loop is not
288    * running, this will cause the next call to loop to terminate soon after
289    * starting.  If a loop runs out of work (and so terminates on its own)
290    * concurrently with a call to terminateLoopSoon(), this may cause a race
291    * condition.
292    *
293    * Note that the caller is responsible for ensuring that cleanup of all event
294    * callbacks occurs properly.  Since terminateLoopSoon() causes the loop to
295    * exit even when there are pending events present, there may be remaining
296    * callbacks present waiting to be invoked.  If the loop is later restarted
297    * pending events will continue to be processed normally, however if the
298    * EventBase is destroyed after calling terminateLoopSoon() it is the
299    * caller's responsibility to ensure that cleanup happens properly even if
300    * some outstanding events are never processed.
301    */
302   void terminateLoopSoon();
303
304   /**
305    * Adds the given callback to a queue of things run after the current pass
306    * through the event loop completes.  Note that if this callback calls
307    * runInLoop() the new callback won't be called until the main event loop
308    * has gone through a cycle.
309    *
310    * This method may only be called from the EventBase's thread.  This
311    * essentially allows an event handler to schedule an additional callback to
312    * be invoked after it returns.
313    *
314    * Use runInEventBaseThread() to schedule functions from another thread.
315    *
316    * The thisIteration parameter makes this callback run in this loop
317    * iteration, instead of the next one, even if called from a
318    * runInLoop callback (normal io callbacks that call runInLoop will
319    * always run in this iteration).  This was originally added to
320    * support detachEventBase, as a user callback may have called
321    * terminateLoopSoon(), but we want to make sure we detach.  Also,
322    * detachEventBase almost always must be called from the base event
323    * loop to ensure the stack is unwound, since most users of
324    * EventBase are not thread safe.
325    *
326    * Ideally we would not need thisIteration, and instead just use
327    * runInLoop with loop() (instead of terminateLoopSoon).
328    */
329   void runInLoop(LoopCallback* callback, bool thisIteration = false);
330
331   /**
332    * Convenience function to call runInLoop() with a folly::Function.
333    *
334    * This creates a LoopCallback object to wrap the folly::Function, and invoke
335    * the folly::Function when the loop callback fires.  This is slightly more
336    * expensive than defining your own LoopCallback, but more convenient in
337    * areas that aren't too performance sensitive.
338    *
339    * This method may only be called from the EventBase's thread.  This
340    * essentially allows an event handler to schedule an additional callback to
341    * be invoked after it returns.
342    *
343    * Use runInEventBaseThread() to schedule functions from another thread.
344    */
345   void runInLoop(Func c, bool thisIteration = false);
346
347   /**
348    * Adds the given callback to a queue of things run before destruction
349    * of current EventBase.
350    *
351    * This allows users of EventBase that run in it, but don't control it,
352    * to be notified before EventBase gets destructed.
353    *
354    * Note: will be called from the thread that invoked EventBase destructor,
355    *       before the final run of loop callbacks.
356    */
357   void runOnDestruction(LoopCallback* callback);
358
359   /**
360    * Adds a callback that will run immediately *before* the event loop.
361    * This is very similar to runInLoop(), but will not cause the loop to break:
362    * For example, this callback could be used to get loop times.
363    */
364   void runBeforeLoop(LoopCallback* callback);
365
366   /**
367    * Run the specified function in the EventBase's thread.
368    *
369    * This method is thread-safe, and may be called from another thread.
370    *
371    * If runInEventBaseThread() is called when the EventBase loop is not
372    * running, the function call will be delayed until the next time the loop is
373    * started.
374    *
375    * If runInEventBaseThread() returns true the function has successfully been
376    * scheduled to run in the loop thread.  However, if the loop is terminated
377    * (and never later restarted) before it has a chance to run the requested
378    * function, the function will be run upon the EventBase's destruction.
379    *
380    * If two calls to runInEventBaseThread() are made from the same thread, the
381    * functions will always be run in the order that they were scheduled.
382    * Ordering between functions scheduled from separate threads is not
383    * guaranteed.
384    *
385    * @param fn  The function to run.  The function must not throw any
386    *     exceptions.
387    * @param arg An argument to pass to the function.
388    *
389    * @return Returns true if the function was successfully scheduled, or false
390    *         if there was an error scheduling the function.
391    */
392   template <typename T>
393   bool runInEventBaseThread(void (*fn)(T*), T* arg);
394
395   /**
396    * Run the specified function in the EventBase's thread
397    *
398    * This version of runInEventBaseThread() takes a folly::Function object.
399    * Note that this may be less efficient than the version that takes a plain
400    * function pointer and void* argument, if moving the function is expensive
401    * (e.g., if it wraps a lambda which captures some values with expensive move
402    * constructors).
403    *
404    * If the loop is terminated (and never later restarted) before it has a
405    * chance to run the requested function, the function will be run upon the
406    * EventBase's destruction.
407    *
408    * The function must not throw any exceptions.
409    */
410   bool runInEventBaseThread(Func fn);
411
412   /*
413    * Like runInEventBaseThread, but the caller waits for the callback to be
414    * executed.
415    */
416   template <typename T>
417   bool runInEventBaseThreadAndWait(void (*fn)(T*), T* arg);
418
419   /*
420    * Like runInEventBaseThread, but the caller waits for the callback to be
421    * executed.
422    */
423   bool runInEventBaseThreadAndWait(Func fn);
424
425   /*
426    * Like runInEventBaseThreadAndWait, except if the caller is already in the
427    * event base thread, the functor is simply run inline.
428    */
429   template <typename T>
430   bool runImmediatelyOrRunInEventBaseThreadAndWait(void (*fn)(T*), T* arg);
431
432   /*
433    * Like runInEventBaseThreadAndWait, except if the caller is already in the
434    * event base thread, the functor is simply run inline.
435    */
436   bool runImmediatelyOrRunInEventBaseThreadAndWait(Func fn);
437
438   /**
439    * Set the maximum desired latency in us and provide a callback which will be
440    * called when that latency is exceeded.
441    * OBS: This functionality depends on time-measurement.
442    */
443   void setMaxLatency(std::chrono::microseconds maxLatency, Func maxLatencyCob) {
444     assert(enableTimeMeasurement_);
445     maxLatency_ = maxLatency;
446     maxLatencyCob_ = std::move(maxLatencyCob);
447   }
448
449   /**
450    * Set smoothing coefficient for loop load average; # of milliseconds
451    * for exp(-1) (1/2.71828...) decay.
452    */
453   void setLoadAvgMsec(std::chrono::milliseconds ms);
454
455   /**
456    * reset the load average to a desired value
457    */
458   void resetLoadAvg(double value = 0.0);
459
460   /**
461    * Get the average loop time in microseconds (an exponentially-smoothed ave)
462    */
463   double getAvgLoopTime() const {
464     assert(enableTimeMeasurement_);
465     return avgLoopTime_.get();
466   }
467
468   /**
469     * check if the event base loop is running.
470    */
471   bool isRunning() const {
472     return loopThread_.load(std::memory_order_relaxed) != std::thread::id();
473   }
474
475   /**
476    * wait until the event loop starts (after starting the event loop thread).
477    */
478   void waitUntilRunning();
479
480   size_t getNotificationQueueSize() const;
481
482   void setMaxReadAtOnce(uint32_t maxAtOnce);
483
484   /**
485    * Verify that current thread is the EventBase thread, if the EventBase is
486    * running.
487    */
488   bool isInEventBaseThread() const {
489     auto tid = loopThread_.load(std::memory_order_relaxed);
490     return tid == std::thread::id() || tid == std::this_thread::get_id();
491   }
492
493   bool inRunningEventBaseThread() const {
494     return loopThread_.load(std::memory_order_relaxed) ==
495         std::this_thread::get_id();
496   }
497
498   /**
499    * Equivalent to CHECK(isInEventBaseThread()) (and assert/DCHECK for
500    * dcheckIsInEventBaseThread), but it prints more information on
501    * failure.
502    */
503   void checkIsInEventBaseThread() const;
504   void dcheckIsInEventBaseThread() const {
505     if (kIsDebug) {
506       checkIsInEventBaseThread();
507     }
508   }
509
510   HHWheelTimer& timer() {
511     if (!wheelTimer_) {
512       wheelTimer_ = HHWheelTimer::newTimer(this);
513     }
514     return *wheelTimer_.get();
515   }
516
517   // --------- interface to underlying libevent base ------------
518   // Avoid using these functions if possible.  These functions are not
519   // guaranteed to always be present if we ever provide alternative EventBase
520   // implementations that do not use libevent internally.
521   event_base* getLibeventBase() const { return evb_; }
522   static const char* getLibeventVersion();
523   static const char* getLibeventMethod();
524
525   /**
526    * only EventHandler/AsyncTimeout subclasses and ourselves should
527    * ever call this.
528    *
529    * This is used to mark the beginning of a new loop cycle by the
530    * first handler fired within that cycle.
531    *
532    */
533   void bumpHandlingTime() final;
534
535   class SmoothLoopTime {
536    public:
537     explicit SmoothLoopTime(std::chrono::microseconds timeInterval)
538         : expCoeff_(-1.0 / timeInterval.count()),
539           value_(0.0),
540           oldBusyLeftover_(0) {
541       VLOG(11) << "expCoeff_ " << expCoeff_ << " " << __PRETTY_FUNCTION__;
542     }
543
544     void setTimeInterval(std::chrono::microseconds timeInterval);
545     void reset(double value = 0.0);
546
547     void addSample(
548         std::chrono::microseconds idle,
549         std::chrono::microseconds busy);
550
551     double get() const {
552       return value_;
553     }
554
555     void dampen(double factor) {
556       value_ *= factor;
557     }
558
559    private:
560     double expCoeff_;
561     double value_;
562     std::chrono::microseconds oldBusyLeftover_;
563   };
564
565   void setObserver(const std::shared_ptr<EventBaseObserver>& observer) {
566     assert(enableTimeMeasurement_);
567     observer_ = observer;
568   }
569
570   const std::shared_ptr<EventBaseObserver>& getObserver() {
571     return observer_;
572   }
573
574   /**
575    * Setup execution observation/instrumentation for every EventHandler
576    * executed in this EventBase.
577    *
578    * @param executionObserver   EventHandle's execution observer.
579    */
580   void setExecutionObserver(ExecutionObserver* observer) {
581     executionObserver_ = observer;
582   }
583
584   /**
585    * Gets the execution observer associated with this EventBase.
586    */
587   ExecutionObserver* getExecutionObserver() {
588     return executionObserver_;
589   }
590
591   /**
592    * Set the name of the thread that runs this event base.
593    */
594   void setName(const std::string& name);
595
596   /**
597    * Returns the name of the thread that runs this event base.
598    */
599   const std::string& getName();
600
601   /// Implements the Executor interface
602   void add(Cob fn) override {
603     // runInEventBaseThread() takes a const&,
604     // so no point in doing std::move here.
605     runInEventBaseThread(std::move(fn));
606   }
607
608   /// Implements the DrivableExecutor interface
609   void drive() override {
610     ++loopKeepAliveCount_;
611     SCOPE_EXIT {
612       --loopKeepAliveCount_;
613     };
614     loopOnce();
615   }
616
617   /// Returns you a handle which make loop() behave like loopForever() until
618   /// destroyed. loop() will return to its original behavior only when all
619   /// loop keep-alives are released.
620   KeepAlive getKeepAliveToken() override {
621     keepAliveAcquire();
622     return makeKeepAlive();
623   }
624
625   // TimeoutManager
626   void attachTimeoutManager(
627       AsyncTimeout* obj,
628       TimeoutManager::InternalEnum internal) final;
629
630   void detachTimeoutManager(AsyncTimeout* obj) final;
631
632   bool scheduleTimeout(AsyncTimeout* obj, TimeoutManager::timeout_type timeout)
633       final;
634
635   void cancelTimeout(AsyncTimeout* obj) final;
636
637   bool isInTimeoutManagerThread() final {
638     return isInEventBaseThread();
639   }
640
641   // Returns a VirtualEventBase attached to this EventBase. Can be used to
642   // pass to APIs which expect VirtualEventBase. This VirtualEventBase will be
643   // destroyed together with the EventBase.
644   //
645   // Any number of VirtualEventBases instances may be independently constructed,
646   // which are backed by this EventBase. This method should be only used if you
647   // don't need to manage the life time of the VirtualEventBase used.
648   folly::VirtualEventBase& getVirtualEventBase();
649
650  protected:
651   void keepAliveAcquire() override {
652     if (inRunningEventBaseThread()) {
653       loopKeepAliveCount_++;
654     } else {
655       loopKeepAliveCountAtomic_.fetch_add(1, std::memory_order_relaxed);
656     }
657   }
658
659   void keepAliveRelease() override {
660     if (!inRunningEventBaseThread()) {
661       return add([=] { keepAliveRelease(); });
662     }
663     loopKeepAliveCount_--;
664   }
665
666  private:
667   void applyLoopKeepAlive();
668
669   ssize_t loopKeepAliveCount();
670
671   /*
672    * Helper function that tells us whether we have already handled
673    * some event/timeout/callback in this loop iteration.
674    */
675   bool nothingHandledYet() const noexcept;
676
677   typedef LoopCallback::List LoopCallbackList;
678   class FunctionRunner;
679
680   bool loopBody(int flags = 0);
681
682   // executes any callbacks queued by runInLoop(); returns false if none found
683   bool runLoopCallbacks();
684
685   void initNotificationQueue();
686
687   // should only be accessed through public getter
688   HHWheelTimer::UniquePtr wheelTimer_;
689
690   LoopCallbackList loopCallbacks_;
691   LoopCallbackList runBeforeLoopCallbacks_;
692   LoopCallbackList onDestructionCallbacks_;
693
694   // This will be null most of the time, but point to currentCallbacks
695   // if we are in the middle of running loop callbacks, such that
696   // runInLoop(..., true) will always run in the current loop
697   // iteration.
698   LoopCallbackList* runOnceCallbacks_;
699
700   // stop_ is set by terminateLoopSoon() and is used by the main loop
701   // to determine if it should exit
702   std::atomic<bool> stop_;
703
704   // The ID of the thread running the main loop.
705   // std::thread::id{} if loop is not running.
706   std::atomic<std::thread::id> loopThread_;
707
708   // pointer to underlying event_base class doing the heavy lifting
709   event_base* evb_;
710
711   // A notification queue for runInEventBaseThread() to use
712   // to send function requests to the EventBase thread.
713   std::unique_ptr<NotificationQueue<Func>> queue_;
714   std::unique_ptr<FunctionRunner> fnRunner_;
715   ssize_t loopKeepAliveCount_{0};
716   std::atomic<ssize_t> loopKeepAliveCountAtomic_{0};
717   bool loopKeepAliveActive_{false};
718
719   // limit for latency in microseconds (0 disables)
720   std::chrono::microseconds maxLatency_;
721
722   // exponentially-smoothed average loop time for latency-limiting
723   SmoothLoopTime avgLoopTime_;
724
725   // smoothed loop time used to invoke latency callbacks; differs from
726   // avgLoopTime_ in that it's scaled down after triggering a callback
727   // to reduce spamminess
728   SmoothLoopTime maxLatencyLoopTime_;
729
730   // callback called when latency limit is exceeded
731   Func maxLatencyCob_;
732
733   // Enables/disables time measurements in loopBody(). if disabled, the
734   // following functionality that relies on time-measurement, will not
735   // be supported: avg loop time, observer and max latency.
736   const bool enableTimeMeasurement_;
737
738   // Wrap-around loop counter to detect beginning of each loop
739   uint64_t nextLoopCnt_;
740   uint64_t latestLoopCnt_;
741   std::chrono::steady_clock::time_point startWork_;
742   // Prevent undefined behavior from invoking event_base_loop() reentrantly.
743   // This is needed since many projects use libevent-1.4, which lacks commit
744   // b557b175c00dc462c1fce25f6e7dd67121d2c001 from
745   // https://github.com/libevent/libevent/.
746   bool invokingLoop_{false};
747
748   // Observer to export counters
749   std::shared_ptr<EventBaseObserver> observer_;
750   uint32_t observerSampleCount_;
751
752   // EventHandler's execution observer.
753   ExecutionObserver* executionObserver_;
754
755   // Name of the thread running this EventBase
756   std::string name_;
757
758   // allow runOnDestruction() to be called from any threads
759   std::mutex onDestructionCallbacksMutex_;
760
761   // see EventBaseLocal
762   friend class detail::EventBaseLocalBase;
763   template <typename T> friend class EventBaseLocal;
764   std::unordered_map<uint64_t, std::shared_ptr<void>> localStorage_;
765   std::unordered_set<detail::EventBaseLocalBaseBase*> localStorageToDtor_;
766
767   folly::once_flag virtualEventBaseInitFlag_;
768   std::unique_ptr<VirtualEventBase> virtualEventBase_;
769 };
770
771 template <typename T>
772 bool EventBase::runInEventBaseThread(void (*fn)(T*), T* arg) {
773   return runInEventBaseThread([=] { fn(arg); });
774 }
775
776 template <typename T>
777 bool EventBase::runInEventBaseThreadAndWait(void (*fn)(T*), T* arg) {
778   return runInEventBaseThreadAndWait([=] { fn(arg); });
779 }
780
781 template <typename T>
782 bool EventBase::runImmediatelyOrRunInEventBaseThreadAndWait(
783     void (*fn)(T*),
784     T* arg) {
785   return runImmediatelyOrRunInEventBaseThreadAndWait([=] { fn(arg); });
786 }
787
788 } // namespace folly