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