| // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef BASE_MESSAGE_LOOP_MESSAGE_PUMP_LIBEVENT_H_ |
| #define BASE_MESSAGE_LOOP_MESSAGE_PUMP_LIBEVENT_H_ |
| |
| #include <memory> |
| |
| #include "base/compiler_specific.h" |
| #include "base/macros.h" |
| #include "base/message_loop/message_pump.h" |
| #include "base/message_loop/watchable_io_message_pump_posix.h" |
| #include "base/threading/thread_checker.h" |
| #include "base/time/time.h" |
| |
| // Declare structs we need from libevent.h rather than including it |
| struct event_base; |
| struct event; |
| |
| namespace base { |
| |
| // Class to monitor sockets and issue callbacks when sockets are ready for I/O |
| // TODO(dkegel): add support for background file IO somehow |
| class BASE_EXPORT MessagePumpLibevent : public MessagePump, |
| public WatchableIOMessagePumpPosix { |
| public: |
| class FdWatchController : public FdWatchControllerInterface { |
| public: |
| explicit FdWatchController(const Location& from_here); |
| |
| // Implicitly calls StopWatchingFileDescriptor. |
| ~FdWatchController() override; |
| |
| // FdWatchControllerInterface: |
| bool StopWatchingFileDescriptor() override; |
| |
| private: |
| friend class MessagePumpLibevent; |
| friend class MessagePumpLibeventTest; |
| |
| // Called by MessagePumpLibevent. |
| void Init(std::unique_ptr<event> e); |
| |
| // Used by MessagePumpLibevent to take ownership of |event_|. |
| std::unique_ptr<event> ReleaseEvent(); |
| |
| void set_pump(MessagePumpLibevent* pump) { pump_ = pump; } |
| MessagePumpLibevent* pump() const { return pump_; } |
| |
| void set_watcher(FdWatcher* watcher) { watcher_ = watcher; } |
| |
| void OnFileCanReadWithoutBlocking(int fd, MessagePumpLibevent* pump); |
| void OnFileCanWriteWithoutBlocking(int fd, MessagePumpLibevent* pump); |
| |
| std::unique_ptr<event> event_; |
| MessagePumpLibevent* pump_ = nullptr; |
| FdWatcher* watcher_ = nullptr; |
| // If this pointer is non-NULL, the pointee is set to true in the |
| // destructor. |
| bool* was_destroyed_ = nullptr; |
| |
| DISALLOW_COPY_AND_ASSIGN(FdWatchController); |
| }; |
| |
| MessagePumpLibevent(); |
| ~MessagePumpLibevent() override; |
| |
| bool WatchFileDescriptor(int fd, |
| bool persistent, |
| int mode, |
| FdWatchController* controller, |
| FdWatcher* delegate); |
| |
| // MessagePump methods: |
| void Run(Delegate* delegate) override; |
| void Quit() override; |
| void ScheduleWork() override; |
| void ScheduleDelayedWork(const TimeTicks& delayed_work_time) override; |
| |
| private: |
| friend class MessagePumpLibeventTest; |
| |
| // Risky part of constructor. Returns true on success. |
| bool Init(); |
| |
| // Called by libevent to tell us a registered FD can be read/written to. |
| static void OnLibeventNotification(int fd, short flags, void* context); |
| |
| // Unix pipe used to implement ScheduleWork() |
| // ... callback; called by libevent inside Run() when pipe is ready to read |
| static void OnWakeup(int socket, short flags, void* context); |
| |
| // This flag is set to false when Run should return. |
| bool keep_running_; |
| |
| // This flag is set when inside Run. |
| bool in_run_; |
| |
| // This flag is set if libevent has processed I/O events. |
| bool processed_io_events_; |
| |
| // The time at which we should call DoDelayedWork. |
| TimeTicks delayed_work_time_; |
| |
| // Libevent dispatcher. Watches all sockets registered with it, and sends |
| // readiness callbacks when a socket is ready for I/O. |
| event_base* event_base_; |
| |
| // ... write end; ScheduleWork() writes a single byte to it |
| int wakeup_pipe_in_; |
| // ... read end; OnWakeup reads it and then breaks Run() out of its sleep |
| int wakeup_pipe_out_; |
| // ... libevent wrapper for read end |
| event* wakeup_event_; |
| |
| ThreadChecker watch_file_descriptor_caller_checker_; |
| DISALLOW_COPY_AND_ASSIGN(MessagePumpLibevent); |
| }; |
| |
| } // namespace base |
| |
| #endif // BASE_MESSAGE_LOOP_MESSAGE_PUMP_LIBEVENT_H_ |