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