1a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved. 2a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 3a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// found in the LICENSE file. 4a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 5effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#ifndef MOJO_PUBLIC_CPP_UTILITY_RUN_LOOP_H_ 6effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#define MOJO_PUBLIC_CPP_UTILITY_RUN_LOOP_H_ 7a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 8a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include <map> 95f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include <queue> 10a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "mojo/public/cpp/bindings/callback.h" 12effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#include "mojo/public/cpp/system/core.h" 13a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 14a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)namespace mojo { 15a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 16a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)class RunLoopHandler; 17a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 18a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)class RunLoop { 19a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) public: 20a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) RunLoop(); 21a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) ~RunLoop(); 22a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 23a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // Sets up state needed for RunLoop. This must be invoked before creating a 24a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // RunLoop. 25a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) static void SetUp(); 26a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 27a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // Cleans state created by Setup(). 28a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) static void TearDown(); 29a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 30a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // Returns the RunLoop for the current thread. Returns NULL if not yet 31a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // created. 32a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) static RunLoop* current(); 33a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 34a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // Registers a RunLoopHandler for the specified handle. Only one handler can 35a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // be registered for a specified handle. 36a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) void AddHandler(RunLoopHandler* handler, 37a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const Handle& handle, 38f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) MojoHandleSignals handle_signals, 39a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) MojoDeadline deadline); 40a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) void RemoveHandler(const Handle& handle); 415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) bool HasHandler(const Handle& handle) const; 42a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Runs the loop servicing handles and tasks as they are ready. This returns 441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // when Quit() is invoked, or there are no more handles nor tasks. 45a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) void Run(); 465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Runs the loop servicing any handles and tasks that are ready. Does not wait 481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // for handles or tasks to become ready before returning. Returns early if 491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Quit() is invoked. 505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) void RunUntilIdle(); 515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 52a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) void Quit(); 53a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Adds a task to be performed after delay has elapsed. Must be posted to the 555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // current thread's RunLoop. 565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) void PostDelayedTask(const Closure& task, MojoTimeTicks delay); 575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 58a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) private: 59a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) struct RunState; 60a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) struct WaitState; 61a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 62a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // Contains the data needed to track a request to AddHandler(). 63a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) struct HandlerData { 64a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) HandlerData() 65a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) : handler(NULL), 66f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) handle_signals(MOJO_HANDLE_SIGNAL_NONE), 67a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) deadline(0), 68a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) id(0) {} 69a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 70a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) RunLoopHandler* handler; 71f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) MojoHandleSignals handle_signals; 72a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) MojoTimeTicks deadline; 73a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // See description of |RunLoop::next_handler_id_| for details. 74a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) int id; 75a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) }; 76a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 77a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) typedef std::map<Handle, HandlerData> HandleToHandlerData; 78a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 7903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // Used for NotifyHandlers to specify whether HandlerData's |deadline| 8003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // should be checked prior to notifying. 8103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) enum CheckDeadline { 8203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) CHECK_DEADLINE, 8303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) IGNORE_DEADLINE 8403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) }; 8503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Mode of operation of the run loop. 871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci enum RunMode { 881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci UNTIL_EMPTY, 891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci UNTIL_IDLE 901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci }; 911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Runs the loop servicing any handles and tasks that are ready. If 931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // |run_mode| is |UNTIL_IDLE|, does not wait for handles or tasks to become 941320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // ready before returning. Returns early if Quit() is invoked. 951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci void RunInternal(RunMode run_mode); 961320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Do one unit of delayed work, if eligible. Returns true is a task was run. 981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci bool DoDelayedWork(); 995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Waits for a handle to be ready or until the next task must be run. Returns 1011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // after servicing at least one handle (or there are no more handles) unless 1021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // a task must be run or |non_blocking| is true, in which case it will also 1031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // return if no task is registered and servicing at least one handle would 1041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // require blocking. Returns true if a RunLoopHandler was notified. 1055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) bool Wait(bool non_blocking); 106a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 10703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // Notifies handlers of |error|. If |check| == CHECK_DEADLINE, this will 10803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // only notify handlers whose deadline has expired and skips the rest. 10903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // Returns true if a RunLoopHandler was notified. 11003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) bool NotifyHandlers(MojoResult error, CheckDeadline check); 111a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 112a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // Removes the first invalid handle. This is called if MojoWaitMany() finds an 1135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // invalid handle. Returns true if a RunLoopHandler was notified. 1145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) bool RemoveFirstInvalidHandle(const WaitState& wait_state); 115a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 116a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // Returns the state needed to pass to WaitMany(). 1175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) WaitState GetWaitState(bool non_blocking) const; 118a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 119a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) HandleToHandlerData handler_data_; 120a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 121a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // If non-NULL we're running (inside Run()). Member references a value on the 122a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // stack. 123a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) RunState* run_state_; 124a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 125a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // An ever increasing value assigned to each HandlerData::id. Used to detect 126a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // uniqueness while notifying. That is, while notifying expired timers we copy 127a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // |handler_data_| and only notify handlers whose id match. If the id does not 128a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // match it means the handler was removed then added so that we shouldn't 129a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // notify it. 130a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) int next_handler_id_; 131a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 1325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) struct PendingTask { 1335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) PendingTask(const Closure& task, 1345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) MojoTimeTicks runtime, 1355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) uint64_t sequence_number); 1365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ~PendingTask(); 1375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) bool operator<(const PendingTask& other) const; 1395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) Closure task; 1415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) MojoTimeTicks run_time; 1425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) uint64_t sequence_number; 1435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) }; 1445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // An ever increasing sequence number attached to each pending task in order 1455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // to preserve relative order of tasks posted at the 'same' time. 1465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) uint64_t next_sequence_number_; 1475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) typedef std::priority_queue<PendingTask> DelayedTaskQueue; 1485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) DelayedTaskQueue delayed_tasks_; 1495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 150a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) MOJO_DISALLOW_COPY_AND_ASSIGN(RunLoop); 151a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}; 152a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 153a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} // namespace mojo 154a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 155effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#endif // MOJO_PUBLIC_CPP_UTILITY_RUN_LOOP_H_ 156