message_pump_kqueue.h 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193
  1. // Copyright 2019 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_KQUEUE_H_
  5. #define BASE_MESSAGE_LOOP_MESSAGE_PUMP_KQUEUE_H_
  6. #include <mach/mach.h>
  7. #include <stdint.h>
  8. #include <sys/event.h>
  9. #include <vector>
  10. #include "base/containers/id_map.h"
  11. #include "base/files/scoped_file.h"
  12. #include "base/location.h"
  13. #include "base/mac/scoped_mach_port.h"
  14. #include "base/memory/raw_ptr.h"
  15. #include "base/memory/weak_ptr.h"
  16. #include "base/message_loop/message_pump.h"
  17. #include "base/message_loop/watchable_io_message_pump_posix.h"
  18. namespace base {
  19. // MessagePumpKqueue is used on macOS to drive an IO MessageLoop that is
  20. // capable of watching both POSIX file descriptors and Mach ports.
  21. class BASE_EXPORT MessagePumpKqueue : public MessagePump,
  22. public WatchableIOMessagePumpPosix {
  23. public:
  24. class FdWatchController : public FdWatchControllerInterface {
  25. public:
  26. explicit FdWatchController(const Location& from_here);
  27. FdWatchController(const FdWatchController&) = delete;
  28. FdWatchController& operator=(const FdWatchController&) = delete;
  29. ~FdWatchController() override;
  30. // FdWatchControllerInterface:
  31. bool StopWatchingFileDescriptor() override;
  32. protected:
  33. friend class MessagePumpKqueue;
  34. void Init(WeakPtr<MessagePumpKqueue> pump,
  35. int fd,
  36. int mode,
  37. FdWatcher* watcher);
  38. void Reset();
  39. int fd() { return fd_; }
  40. int mode() { return mode_; }
  41. FdWatcher* watcher() { return watcher_; }
  42. private:
  43. int fd_ = -1;
  44. int mode_ = 0;
  45. raw_ptr<FdWatcher> watcher_ = nullptr;
  46. WeakPtr<MessagePumpKqueue> pump_;
  47. };
  48. // Delegate interface that provides notifications of Mach message receive
  49. // events.
  50. class MachPortWatcher {
  51. public:
  52. virtual ~MachPortWatcher() {}
  53. virtual void OnMachMessageReceived(mach_port_t port) = 0;
  54. };
  55. // Controller interface that is used to stop receiving events for an
  56. // installed MachPortWatcher.
  57. class MachPortWatchController {
  58. public:
  59. explicit MachPortWatchController(const Location& from_here);
  60. MachPortWatchController(const MachPortWatchController&) = delete;
  61. MachPortWatchController& operator=(const MachPortWatchController&) = delete;
  62. ~MachPortWatchController();
  63. bool StopWatchingMachPort();
  64. protected:
  65. friend class MessagePumpKqueue;
  66. void Init(WeakPtr<MessagePumpKqueue> pump,
  67. mach_port_t port,
  68. MachPortWatcher* watcher);
  69. void Reset();
  70. mach_port_t port() { return port_; }
  71. MachPortWatcher* watcher() { return watcher_; }
  72. private:
  73. mach_port_t port_ = MACH_PORT_NULL;
  74. raw_ptr<MachPortWatcher> watcher_ = nullptr;
  75. WeakPtr<MessagePumpKqueue> pump_;
  76. const Location from_here_;
  77. };
  78. MessagePumpKqueue();
  79. MessagePumpKqueue(const MessagePumpKqueue&) = delete;
  80. MessagePumpKqueue& operator=(const MessagePumpKqueue&) = delete;
  81. ~MessagePumpKqueue() override;
  82. // MessagePump:
  83. void Run(Delegate* delegate) override;
  84. void Quit() override;
  85. void ScheduleWork() override;
  86. void ScheduleDelayedWork(
  87. const Delegate::NextWorkInfo& next_work_info) override;
  88. // Begins watching the Mach receive right named by |port|. The |controller|
  89. // can be used to stop watching for incoming messages, and new message
  90. // notifications are delivered to the |delegate|. Returns true if the watch
  91. // was successfully set-up and false on error.
  92. bool WatchMachReceivePort(mach_port_t port,
  93. MachPortWatchController* controller,
  94. MachPortWatcher* delegate);
  95. // WatchableIOMessagePumpPosix:
  96. bool WatchFileDescriptor(int fd,
  97. bool persistent,
  98. int mode,
  99. FdWatchController* controller,
  100. FdWatcher* delegate);
  101. private:
  102. // Called by the watch controller implementations to stop watching the
  103. // respective types of handles.
  104. bool StopWatchingMachPort(MachPortWatchController* controller);
  105. bool StopWatchingFileDescriptor(FdWatchController* controller);
  106. // Checks the |kqueue_| for events. If |next_work_info| is null, then the
  107. // kqueue will be polled for events. If it is non-null, it will wait for the
  108. // amount of time specified by the NextWorkInfo or until an event is
  109. // triggered. Returns whether any events were dispatched, with the events
  110. // stored in |events_|.
  111. bool DoInternalWork(Delegate* delegate,
  112. Delegate::NextWorkInfo* next_work_info);
  113. // Called by DoInternalWork() to dispatch the user events stored in |events_|
  114. // that were triggered. |count| is the number of events to process. Returns
  115. // true if work was done, or false if no work was done.
  116. bool ProcessEvents(Delegate* delegate, size_t count);
  117. // Updates the wakeup timer to |wakeup_time| if it differs from the currently
  118. // scheduled wakeup. Clears the wakeup timer if |wakeup_time| is
  119. // base::TimeTicks::Max().
  120. // Updates |scheduled_wakeup_time_| to follow.
  121. void MaybeUpdateWakeupTimer(const base::TimeTicks& wakeup_time);
  122. void SetWakeupTimerEvent(const base::TimeTicks& wakeup_time,
  123. kevent64_s* timer_event);
  124. // Receive right to which an empty Mach message is sent to wake up the pump
  125. // in response to ScheduleWork().
  126. mac::ScopedMachReceiveRight wakeup_;
  127. // Scratch buffer that is used to receive the message sent to |wakeup_|.
  128. mach_msg_empty_rcv_t wakeup_buffer_;
  129. // Watch controllers for FDs. IDs are generated by the map and are stored in
  130. // the kevent64_s::udata field.
  131. IDMap<FdWatchController*, uint64_t> fd_controllers_;
  132. // Watch controllers for Mach ports. IDs are the port being watched.
  133. IDMap<MachPortWatchController*, mach_port_t> port_controllers_;
  134. // The kqueue that drives the pump.
  135. ScopedFD kqueue_;
  136. // Whether the pump has been Quit() or not.
  137. bool keep_running_ = true;
  138. // The currently scheduled wakeup, if any. If no wakeup is scheduled,
  139. // contains base::TimeTicks::Max().
  140. base::TimeTicks scheduled_wakeup_time_{base::TimeTicks::Max()};
  141. // The number of events scheduled on the |kqueue_|. There is always at least
  142. // 1, for the |wakeup_| port.
  143. size_t event_count_ = 1;
  144. // Buffer used by DoInternalWork() to be notified of triggered events. This
  145. // is always at least |event_count_|-sized.
  146. std::vector<kevent64_s> events_{event_count_};
  147. WeakPtrFactory<MessagePumpKqueue> weak_factory_;
  148. };
  149. } // namespace base
  150. #endif // BASE_MESSAGE_LOOP_MESSAGE_PUMP_KQUEUE_H_