1 // Copyright 2015 The Chromium OS 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 LIBBRILLO_BRILLO_MESSAGE_LOOPS_BASE_MESSAGE_LOOP_H_ 6 #define LIBBRILLO_BRILLO_MESSAGE_LOOPS_BASE_MESSAGE_LOOP_H_ 7 8 // BaseMessageLoop is a brillo::MessageLoop implementation based on 9 // base::MessageLoopForIO. This allows to mix new code using 10 // brillo::MessageLoop and legacy code using base::MessageLoopForIO in the 11 // same thread and share a single main loop. This disadvantage of using this 12 // class is a less efficient implementation of CancelTask() for delayed tasks 13 // since base::MessageLoopForIO doesn't provide a way to remove the event. 14 15 #include <map> 16 #include <memory> 17 #include <string> 18 19 #include <base/location.h> 20 #include <base/memory/weak_ptr.h> 21 #include <base/message_loop/message_loop.h> 22 #include <base/message_loop/message_pump_for_io.h> 23 #include <base/time/time.h> 24 #include <gtest/gtest_prod.h> 25 26 #include <brillo/brillo_export.h> 27 #include <brillo/message_loops/message_loop.h> 28 29 namespace brillo { 30 31 class BRILLO_EXPORT BaseMessageLoop : public MessageLoop { 32 public: 33 // Construct a base::MessageLoopForIO message loop instance and use it as 34 // the default message loop for this thread. 35 BaseMessageLoop(); 36 37 // Construct a brillo::BaseMessageLoop using the passed base::MessageLoopForIO 38 // instance. 39 explicit BaseMessageLoop(base::MessageLoopForIO* base_loop); 40 ~BaseMessageLoop() override; 41 42 // MessageLoop overrides. 43 TaskId PostDelayedTask(const base::Location& from_here, 44 const base::Closure& task, 45 base::TimeDelta delay) override; 46 using MessageLoop::PostDelayedTask; 47 TaskId WatchFileDescriptor(const base::Location& from_here, 48 int fd, 49 WatchMode mode, 50 bool persistent, 51 const base::Closure& task) override; 52 using MessageLoop::WatchFileDescriptor; 53 bool CancelTask(TaskId task_id) override; 54 bool RunOnce(bool may_block) override; 55 void Run() override; 56 void BreakLoop() override; 57 58 // Returns a callback that will quit the current message loop. If the message 59 // loop is not running, an empty (null) callback is returned. 60 base::Closure QuitClosure() const; 61 62 private: 63 FRIEND_TEST(BaseMessageLoopTest, ParseBinderMinor); 64 65 static const int kInvalidMinor; 66 static const int kUninitializedMinor; 67 68 // Parses the contents of the file /proc/misc passed in |file_contents| and 69 // returns the minor device number reported for binder. On error or if not 70 // found, returns kInvalidMinor. 71 static int ParseBinderMinor(const std::string& file_contents); 72 73 // Called by base::MessageLoopForIO when is time to call the callback 74 // scheduled with Post*Task() of id |task_id|, even if it was canceled. 75 void OnRanPostedTask(MessageLoop::TaskId task_id); 76 77 // Called from the message loop when the IOTask should run the scheduled 78 // callback. This is a simple wrapper of IOTask::OnFileReadyPostedTask() 79 // posted from the BaseMessageLoop so it is deleted when the BaseMessageLoop 80 // goes out of scope since we can't cancel the callback otherwise. 81 void OnFileReadyPostedTask(MessageLoop::TaskId task_id); 82 83 // Return a new unused task_id. 84 TaskId NextTaskId(); 85 86 // Returns binder minor device number. 87 unsigned int GetBinderMinor(); 88 89 struct DelayedTask { 90 base::Location location; 91 92 MessageLoop::TaskId task_id; 93 base::Closure closure; 94 }; 95 96 class IOTask : public base::MessagePumpForIO::FdWatcher { 97 public: 98 IOTask(const base::Location& location, 99 BaseMessageLoop* loop, 100 MessageLoop::TaskId task_id, 101 int fd, 102 base::MessagePumpForIO::Mode base_mode, 103 bool persistent, 104 const base::Closure& task); 105 location()106 const base::Location& location() const { return location_; } 107 108 // Used to start/stop watching the file descriptor while keeping the 109 // IOTask entry available. 110 bool StartWatching(); 111 void StopWatching(); 112 113 // Called from the message loop as a PostTask() when the file descriptor is 114 // available, scheduled to run from OnFileReady(). 115 void OnFileReadyPostedTask(); 116 117 // Cancel the IOTask and returns whether it was actually canceled, with the 118 // same semantics as MessageLoop::CancelTask(). 119 bool CancelTask(); 120 121 // Sets the closure to be run immediately whenever the file descriptor 122 // becomes ready. RunImmediately()123 void RunImmediately() { immediate_run_= true; } 124 125 private: 126 base::Location location_; 127 BaseMessageLoop* loop_; 128 129 // These are the arguments passed in the constructor, basically forwarding 130 // all the arguments passed to WatchFileDescriptor() plus the assigned 131 // TaskId for this task. 132 MessageLoop::TaskId task_id_; 133 int fd_; 134 base::MessagePumpForIO::Mode base_mode_; 135 bool persistent_; 136 base::Closure closure_; 137 138 base::MessagePumpForIO::FdWatchController fd_watcher_; 139 140 // Tells whether there is a pending call to OnFileReadPostedTask(). 141 bool posted_task_pending_{false}; 142 143 // Whether the registered callback should be running immediately when the 144 // file descriptor is ready, as opposed to posting a task to the main loop 145 // to prevent starvation. 146 bool immediate_run_{false}; 147 148 // base::MessageLoopForIO::Watcher overrides: 149 void OnFileCanReadWithoutBlocking(int fd) override; 150 void OnFileCanWriteWithoutBlocking(int fd) override; 151 152 // Common implementation for both the read and write case. 153 void OnFileReady(); 154 155 DISALLOW_COPY_AND_ASSIGN(IOTask); 156 }; 157 158 // The base::MessageLoopForIO instance owned by this class, if any. This 159 // is declared first in this class so it is destroyed last. 160 std::unique_ptr<base::MessageLoopForIO> owned_base_loop_; 161 162 // Tasks blocked on a timeout. 163 std::map<MessageLoop::TaskId, DelayedTask> delayed_tasks_; 164 165 // Tasks blocked on I/O. 166 std::map<MessageLoop::TaskId, IOTask> io_tasks_; 167 168 // Flag to mark that we should run the message loop only one iteration. 169 bool run_once_{false}; 170 171 // The last used TaskId. While base::MessageLoopForIO doesn't allow to cancel 172 // delayed tasks, we handle that functionality by not running the callback 173 // if it fires at a later point. 174 MessageLoop::TaskId last_id_{kTaskIdNull}; 175 176 // The pointer to the libchrome base::MessageLoopForIO we are wrapping with 177 // this interface. If the instance was created from this object, this will 178 // point to that instance. 179 base::MessageLoopForIO* base_loop_; 180 181 // The RunLoop instance used to run the main loop from Run(). 182 base::RunLoop* base_run_loop_{nullptr}; 183 184 // The binder minor device number. Binder is a "misc" char device with a 185 // dynamically allocated minor number. When uninitialized, this value will 186 // be negative, otherwise, it will hold the minor part of the binder device 187 // number. This is populated by GetBinderMinor(). 188 int binder_minor_{kUninitializedMinor}; 189 190 // We use a WeakPtrFactory to schedule tasks with the base::MessageLoopForIO 191 // since we can't cancel the callbacks we have scheduled there once this 192 // instance is destroyed. 193 base::WeakPtrFactory<BaseMessageLoop> weak_ptr_factory_{this}; 194 DISALLOW_COPY_AND_ASSIGN(BaseMessageLoop); 195 }; 196 197 } // namespace brillo 198 199 #endif // LIBBRILLO_BRILLO_MESSAGE_LOOPS_BASE_MESSAGE_LOOP_H_ 200