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