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 
5 #ifndef BASE_MESSAGE_LOOP_MESSAGE_PUMP_LIBEVENT_H_
6 #define BASE_MESSAGE_LOOP_MESSAGE_PUMP_LIBEVENT_H_
7 
8 #include <memory>
9 
10 #include "base/compiler_specific.h"
11 #include "base/macros.h"
12 #include "base/message_loop/message_pump.h"
13 #include "base/message_loop/watchable_io_message_pump_posix.h"
14 #include "base/threading/thread_checker.h"
15 #include "base/time/time.h"
16 
17 // Declare structs we need from libevent.h rather than including it
18 struct event_base;
19 struct event;
20 
21 namespace base {
22 
23 // Class to monitor sockets and issue callbacks when sockets are ready for I/O
24 // TODO(dkegel): add support for background file IO somehow
25 class BASE_EXPORT MessagePumpLibevent : public MessagePump,
26                                         public WatchableIOMessagePumpPosix {
27  public:
28   class FdWatchController : public FdWatchControllerInterface {
29    public:
30     explicit FdWatchController(const Location& from_here);
31 
32     // Implicitly calls StopWatchingFileDescriptor.
33     ~FdWatchController() override;
34 
35     // FdWatchControllerInterface:
36     bool StopWatchingFileDescriptor() override;
37 
38    private:
39     friend class MessagePumpLibevent;
40     friend class MessagePumpLibeventTest;
41 
42     // Called by MessagePumpLibevent.
43     void Init(std::unique_ptr<event> e);
44 
45     // Used by MessagePumpLibevent to take ownership of |event_|.
46     std::unique_ptr<event> ReleaseEvent();
47 
set_pump(MessagePumpLibevent * pump)48     void set_pump(MessagePumpLibevent* pump) { pump_ = pump; }
pump()49     MessagePumpLibevent* pump() const { return pump_; }
50 
set_watcher(FdWatcher * watcher)51     void set_watcher(FdWatcher* watcher) { watcher_ = watcher; }
52 
53     void OnFileCanReadWithoutBlocking(int fd, MessagePumpLibevent* pump);
54     void OnFileCanWriteWithoutBlocking(int fd, MessagePumpLibevent* pump);
55 
56     std::unique_ptr<event> event_;
57     MessagePumpLibevent* pump_ = nullptr;
58     FdWatcher* watcher_ = nullptr;
59     // If this pointer is non-NULL, the pointee is set to true in the
60     // destructor.
61     bool* was_destroyed_ = nullptr;
62 
63     DISALLOW_COPY_AND_ASSIGN(FdWatchController);
64   };
65 
66   MessagePumpLibevent();
67   ~MessagePumpLibevent() override;
68 
69   bool WatchFileDescriptor(int fd,
70                            bool persistent,
71                            int mode,
72                            FdWatchController* controller,
73                            FdWatcher* delegate);
74 
75   // MessagePump methods:
76   void Run(Delegate* delegate) override;
77   void Quit() override;
78   void ScheduleWork() override;
79   void ScheduleDelayedWork(const TimeTicks& delayed_work_time) override;
80 
81  private:
82   friend class MessagePumpLibeventTest;
83 
84   // Risky part of constructor.  Returns true on success.
85   bool Init();
86 
87   // Called by libevent to tell us a registered FD can be read/written to.
88   static void OnLibeventNotification(int fd, short flags, void* context);
89 
90   // Unix pipe used to implement ScheduleWork()
91   // ... callback; called by libevent inside Run() when pipe is ready to read
92   static void OnWakeup(int socket, short flags, void* context);
93 
94   // This flag is set to false when Run should return.
95   bool keep_running_;
96 
97   // This flag is set when inside Run.
98   bool in_run_;
99 
100   // This flag is set if libevent has processed I/O events.
101   bool processed_io_events_;
102 
103   // The time at which we should call DoDelayedWork.
104   TimeTicks delayed_work_time_;
105 
106   // Libevent dispatcher.  Watches all sockets registered with it, and sends
107   // readiness callbacks when a socket is ready for I/O.
108   event_base* event_base_;
109 
110   // ... write end; ScheduleWork() writes a single byte to it
111   int wakeup_pipe_in_;
112   // ... read end; OnWakeup reads it and then breaks Run() out of its sleep
113   int wakeup_pipe_out_;
114   // ... libevent wrapper for read end
115   event* wakeup_event_;
116 
117   ThreadChecker watch_file_descriptor_caller_checker_;
118   DISALLOW_COPY_AND_ASSIGN(MessagePumpLibevent);
119 };
120 
121 }  // namespace base
122 
123 #endif  // BASE_MESSAGE_LOOP_MESSAGE_PUMP_LIBEVENT_H_
124