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