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