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