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