Home | History | Annotate | Download | only in utility
      1 // Copyright 2013 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 MOJO_PUBLIC_CPP_UTILITY_RUN_LOOP_H_
      6 #define MOJO_PUBLIC_CPP_UTILITY_RUN_LOOP_H_
      7 
      8 #include <map>
      9 #include <queue>
     10 
     11 #include "mojo/public/cpp/bindings/callback.h"
     12 #include "mojo/public/cpp/system/core.h"
     13 
     14 namespace mojo {
     15 
     16 class RunLoopHandler;
     17 
     18 class RunLoop {
     19  public:
     20   RunLoop();
     21   ~RunLoop();
     22 
     23   // Sets up state needed for RunLoop. This must be invoked before creating a
     24   // RunLoop.
     25   static void SetUp();
     26 
     27   // Cleans state created by Setup().
     28   static void TearDown();
     29 
     30   // Returns the RunLoop for the current thread. Returns NULL if not yet
     31   // created.
     32   static RunLoop* current();
     33 
     34   // Registers a RunLoopHandler for the specified handle. Only one handler can
     35   // be registered for a specified handle.
     36   void AddHandler(RunLoopHandler* handler,
     37                   const Handle& handle,
     38                   MojoHandleSignals handle_signals,
     39                   MojoDeadline deadline);
     40   void RemoveHandler(const Handle& handle);
     41   bool HasHandler(const Handle& handle) const;
     42 
     43   // Runs the loop servicing handles and tasks as they are ready. This returns
     44   // when Quit() is invoked, or there are no more handles nor tasks.
     45   void Run();
     46 
     47   // Runs the loop servicing any handles and tasks that are ready. Does not wait
     48   // for handles or tasks to become ready before returning. Returns early if
     49   // Quit() is invoked.
     50   void RunUntilIdle();
     51 
     52   void Quit();
     53 
     54   // Adds a task to be performed after delay has elapsed. Must be posted to the
     55   // current thread's RunLoop.
     56   void PostDelayedTask(const Closure& task, MojoTimeTicks delay);
     57 
     58  private:
     59   struct RunState;
     60   struct WaitState;
     61 
     62   // Contains the data needed to track a request to AddHandler().
     63   struct HandlerData {
     64     HandlerData()
     65         : handler(NULL),
     66           handle_signals(MOJO_HANDLE_SIGNAL_NONE),
     67           deadline(0),
     68           id(0) {}
     69 
     70     RunLoopHandler* handler;
     71     MojoHandleSignals handle_signals;
     72     MojoTimeTicks deadline;
     73     // See description of |RunLoop::next_handler_id_| for details.
     74     int id;
     75   };
     76 
     77   typedef std::map<Handle, HandlerData> HandleToHandlerData;
     78 
     79   // Used for NotifyHandlers to specify whether HandlerData's |deadline|
     80   // should be checked prior to notifying.
     81   enum CheckDeadline {
     82     CHECK_DEADLINE,
     83     IGNORE_DEADLINE
     84   };
     85 
     86   // Mode of operation of the run loop.
     87   enum RunMode {
     88     UNTIL_EMPTY,
     89     UNTIL_IDLE
     90   };
     91 
     92   // Runs the loop servicing any handles and tasks that are ready. If
     93   // |run_mode| is |UNTIL_IDLE|, does not wait for handles or tasks to become
     94   // ready before returning. Returns early if Quit() is invoked.
     95   void RunInternal(RunMode run_mode);
     96 
     97   // Do one unit of delayed work, if eligible. Returns true is a task was run.
     98   bool DoDelayedWork();
     99 
    100   // Waits for a handle to be ready or until the next task must be run. Returns
    101   // after servicing at least one handle (or there are no more handles) unless
    102   // a task must be run or |non_blocking| is true, in which case it will also
    103   // return if no task is registered and servicing at least one handle would
    104   // require blocking. Returns true if a RunLoopHandler was notified.
    105   bool Wait(bool non_blocking);
    106 
    107   // Notifies handlers of |error|.  If |check| == CHECK_DEADLINE, this will
    108   // only notify handlers whose deadline has expired and skips the rest.
    109   // Returns true if a RunLoopHandler was notified.
    110   bool NotifyHandlers(MojoResult error, CheckDeadline check);
    111 
    112   // Removes the first invalid handle. This is called if MojoWaitMany() finds an
    113   // invalid handle. Returns true if a RunLoopHandler was notified.
    114   bool RemoveFirstInvalidHandle(const WaitState& wait_state);
    115 
    116   // Returns the state needed to pass to WaitMany().
    117   WaitState GetWaitState(bool non_blocking) const;
    118 
    119   HandleToHandlerData handler_data_;
    120 
    121   // If non-NULL we're running (inside Run()). Member references a value on the
    122   // stack.
    123   RunState* run_state_;
    124 
    125   // An ever increasing value assigned to each HandlerData::id. Used to detect
    126   // uniqueness while notifying. That is, while notifying expired timers we copy
    127   // |handler_data_| and only notify handlers whose id match. If the id does not
    128   // match it means the handler was removed then added so that we shouldn't
    129   // notify it.
    130   int next_handler_id_;
    131 
    132   struct PendingTask {
    133     PendingTask(const Closure& task,
    134                 MojoTimeTicks runtime,
    135                 uint64_t sequence_number);
    136     ~PendingTask();
    137 
    138     bool operator<(const PendingTask& other) const;
    139 
    140     Closure task;
    141     MojoTimeTicks run_time;
    142     uint64_t sequence_number;
    143   };
    144   // An ever increasing sequence number attached to each pending task in order
    145   // to preserve relative order of tasks posted at the 'same' time.
    146   uint64_t next_sequence_number_;
    147   typedef std::priority_queue<PendingTask> DelayedTaskQueue;
    148   DelayedTaskQueue delayed_tasks_;
    149 
    150   MOJO_DISALLOW_COPY_AND_ASSIGN(RunLoop);
    151 };
    152 
    153 }  // namespace mojo
    154 
    155 #endif  // MOJO_PUBLIC_CPP_UTILITY_RUN_LOOP_H_
    156