message_pump_libevent.h 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245
  1. // Copyright (c) 2012 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #ifndef BASE_MESSAGE_LOOP_MESSAGE_PUMP_LIBEVENT_H_
  5. #define BASE_MESSAGE_LOOP_MESSAGE_PUMP_LIBEVENT_H_
  6. #include <memory>
  7. #include <tuple>
  8. #include "base/base_export.h"
  9. #include "base/compiler_specific.h"
  10. #include "base/memory/raw_ptr.h"
  11. #include "base/memory/weak_ptr.h"
  12. #include "base/message_loop/message_pump.h"
  13. #include "base/message_loop/message_pump_buildflags.h"
  14. #include "base/message_loop/watchable_io_message_pump_posix.h"
  15. #include "base/threading/thread_checker.h"
  16. #include "third_party/libevent/event.h"
  17. // Declare structs we need from libevent.h rather than including it
  18. struct event_base;
  19. struct event;
  20. namespace base {
  21. class MessagePumpEpoll;
  22. // Class to monitor sockets and issue callbacks when sockets are ready for I/O
  23. // TODO(dkegel): add support for background file IO somehow
  24. class BASE_EXPORT MessagePumpLibevent : public MessagePump,
  25. public WatchableIOMessagePumpPosix {
  26. public:
  27. class FdWatchController;
  28. // Parameters used to construct and describe an EpollInterest.
  29. struct EpollInterestParams {
  30. // The file descriptor of interest.
  31. int fd;
  32. // Indicates an interest in being able to read() from `fd`.
  33. bool read;
  34. // Indicates an interest in being able to write() to `fd`.
  35. bool write;
  36. // Indicates whether this interest is a one-shot interest, meaning that it
  37. // must be automatically deactivated every time it triggers an epoll event.
  38. bool one_shot;
  39. bool IsEqual(const EpollInterestParams& rhs) const {
  40. return std::tie(fd, read, write, one_shot) ==
  41. std::tie(rhs.fd, rhs.read, rhs.write, rhs.one_shot);
  42. }
  43. };
  44. // Represents a single controller's interest in a file descriptor via epoll,
  45. // and tracks whether that interest is currently active. Though an interest
  46. // persists as long as its controller is alive and hasn't changed interests,
  47. // it only participates in epoll waits while active. These objects are only
  48. // used when MessagePumpLibevent is configured to use the epoll API instead of
  49. // libevent.
  50. class EpollInterest : public RefCounted<EpollInterest> {
  51. public:
  52. EpollInterest(FdWatchController* controller,
  53. const EpollInterestParams& params);
  54. EpollInterest(const EpollInterest&) = delete;
  55. EpollInterest& operator=(const EpollInterest&) = delete;
  56. FdWatchController* controller() { return controller_; }
  57. const EpollInterestParams& params() const { return params_; }
  58. bool active() const { return active_; }
  59. void set_active(bool active) { active_ = active; }
  60. private:
  61. friend class RefCounted<EpollInterest>;
  62. ~EpollInterest();
  63. FdWatchController* const controller_;
  64. const EpollInterestParams params_;
  65. bool active_ = true;
  66. };
  67. // Note that this class is used as the FdWatchController for both
  68. // MessagePumpLibevent *and* MessagePumpEpoll in order to avoid unnecessary
  69. // code churn during experimentation and eventual transition. Consumers
  70. // construct their own FdWatchController instances, so switching this type
  71. // at runtime would require potentially complex logic changes to all
  72. // consumers.
  73. class FdWatchController : public FdWatchControllerInterface {
  74. public:
  75. explicit FdWatchController(const Location& from_here);
  76. FdWatchController(const FdWatchController&) = delete;
  77. FdWatchController& operator=(const FdWatchController&) = delete;
  78. // Implicitly calls StopWatchingFileDescriptor.
  79. ~FdWatchController() override;
  80. // FdWatchControllerInterface:
  81. bool StopWatchingFileDescriptor() override;
  82. private:
  83. friend class MessagePumpEpoll;
  84. friend class MessagePumpLibevent;
  85. friend class MessagePumpLibeventTest;
  86. // Common methods called by both pump implementations.
  87. void set_watcher(FdWatcher* watcher) { watcher_ = watcher; }
  88. // Methods called only by MessagePumpLibevent
  89. void set_libevent_pump(MessagePumpLibevent* pump) { libevent_pump_ = pump; }
  90. MessagePumpLibevent* libevent_pump() const { return libevent_pump_; }
  91. void Init(std::unique_ptr<event> e);
  92. std::unique_ptr<event> ReleaseEvent();
  93. void OnFileCanReadWithoutBlocking(int fd, MessagePumpLibevent* pump);
  94. void OnFileCanWriteWithoutBlocking(int fd, MessagePumpLibevent* pump);
  95. // Methods called only by MessagePumpEpoll
  96. void set_epoll_pump(WeakPtr<MessagePumpEpoll> pump) {
  97. epoll_pump_ = std::move(pump);
  98. }
  99. const scoped_refptr<EpollInterest>& epoll_interest() const {
  100. return epoll_interest_;
  101. }
  102. // Creates a new Interest described by `params` and adopts it as this
  103. // controller's exclusive interest. Any prior interest is dropped by the
  104. // controller and should be unregistered on the MessagePumpEpoll.
  105. const scoped_refptr<EpollInterest>& AssignEpollInterest(
  106. const EpollInterestParams& params);
  107. void OnFdReadable();
  108. void OnFdWritable();
  109. // Common state
  110. raw_ptr<FdWatcher> watcher_ = nullptr;
  111. // If this pointer is non-null when the FdWatchController is destroyed, the
  112. // pointee is set to true.
  113. raw_ptr<bool> was_destroyed_ = nullptr;
  114. // State used only with libevent
  115. std::unique_ptr<event> event_;
  116. raw_ptr<MessagePumpLibevent> libevent_pump_ = nullptr;
  117. // State used only with epoll
  118. WeakPtr<MessagePumpEpoll> epoll_pump_;
  119. scoped_refptr<EpollInterest> epoll_interest_;
  120. };
  121. MessagePumpLibevent();
  122. #if BUILDFLAG(ENABLE_MESSAGE_PUMP_EPOLL)
  123. // Constructs a MessagePumpLibevent which is forced to use epoll directly
  124. // instead of libevent.
  125. enum { kUseEpoll };
  126. explicit MessagePumpLibevent(decltype(kUseEpoll));
  127. #endif
  128. MessagePumpLibevent(const MessagePumpLibevent&) = delete;
  129. MessagePumpLibevent& operator=(const MessagePumpLibevent&) = delete;
  130. ~MessagePumpLibevent() override;
  131. // Must be called early in process startup, but after FeatureList
  132. // initialization. This allows MessagePumpLibevent to query and cache the
  133. // enabled state of any relevant features.
  134. static void InitializeFeatures();
  135. bool WatchFileDescriptor(int fd,
  136. bool persistent,
  137. int mode,
  138. FdWatchController* controller,
  139. FdWatcher* delegate);
  140. // MessagePump methods:
  141. void Run(Delegate* delegate) override;
  142. void Quit() override;
  143. void ScheduleWork() override;
  144. void ScheduleDelayedWork(
  145. const Delegate::NextWorkInfo& next_work_info) override;
  146. private:
  147. friend class MessagePumpLibeventTest;
  148. // Risky part of constructor. Returns true on success.
  149. bool Init();
  150. // Called by libevent to tell us a registered FD can be read/written to.
  151. static void OnLibeventNotification(int fd, short flags, void* context);
  152. // Unix pipe used to implement ScheduleWork()
  153. // ... callback; called by libevent inside Run() when pipe is ready to read
  154. static void OnWakeup(int socket, short flags, void* context);
  155. struct RunState {
  156. explicit RunState(Delegate* delegate_in) : delegate(delegate_in) {}
  157. // `delegate` is not a raw_ptr<...> for performance reasons (based on
  158. // analysis of sampling profiler data and tab_search:top100:2020).
  159. RAW_PTR_EXCLUSION Delegate* const delegate;
  160. // Used to flag that the current Run() invocation should return ASAP.
  161. bool should_quit = false;
  162. };
  163. #if BUILDFLAG(ENABLE_MESSAGE_PUMP_EPOLL)
  164. // If direct use of epoll is enabled, this is the MessagePumpEpoll instance
  165. // used. In that case, all libevent state below is ignored and unused.
  166. // Otherwise this is null.
  167. std::unique_ptr<MessagePumpEpoll> epoll_pump_;
  168. #endif
  169. // State for the current invocation of Run(). null if not running.
  170. RunState* run_state_ = nullptr;
  171. // This flag is set if libevent has processed I/O events.
  172. bool processed_io_events_ = false;
  173. struct EventBaseFree {
  174. inline void operator()(event_base* e) const {
  175. if (e)
  176. event_base_free(e);
  177. }
  178. };
  179. // Libevent dispatcher. Watches all sockets registered with it, and sends
  180. // readiness callbacks when a socket is ready for I/O.
  181. std::unique_ptr<event_base, EventBaseFree> event_base_{event_base_new()};
  182. // ... write end; ScheduleWork() writes a single byte to it
  183. int wakeup_pipe_in_ = -1;
  184. // ... read end; OnWakeup reads it and then breaks Run() out of its sleep
  185. int wakeup_pipe_out_ = -1;
  186. // ... libevent wrapper for read end
  187. std::unique_ptr<event> wakeup_event_;
  188. ThreadChecker watch_file_descriptor_caller_checker_;
  189. };
  190. } // namespace base
  191. #endif // BASE_MESSAGE_LOOP_MESSAGE_PUMP_LIBEVENT_H_