Home | History | Annotate | Download | only in message_loops
      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 
    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.
    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