1ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo// Copyright 2015 The Chromium OS Authors. All rights reserved. 2ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo// Use of this source code is governed by a BSD-style license that can be 3ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo// found in the LICENSE file. 4ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo 5fed60b0c640828b320f56293c8bebc43fd2b1da8Alex Vakulenko#ifndef LIBBRILLO_BRILLO_MESSAGE_LOOPS_MESSAGE_LOOP_H_ 6fed60b0c640828b320f56293c8bebc43fd2b1da8Alex Vakulenko#define LIBBRILLO_BRILLO_MESSAGE_LOOPS_MESSAGE_LOOP_H_ 7ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo 8ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo#include <string> 9ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo 10ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo#include <base/callback.h> 11106edd138a59b2fa3856028baa15201d4f7f3ffdAlex Deymo#include <base/location.h> 12ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo#include <base/time/time.h> 139ed0cab99f18acb3570a35e9408f24355f6b8324Alex Vakulenko#include <brillo/brillo_export.h> 14ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo 159ed0cab99f18acb3570a35e9408f24355f6b8324Alex Vakulenkonamespace brillo { 16ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo 179ed0cab99f18acb3570a35e9408f24355f6b8324Alex Vakulenkoclass BRILLO_EXPORT MessageLoop { 18ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo public: 19ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo virtual ~MessageLoop(); 20ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo 21ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo // A unique task identifier used to refer to scheduled callbacks. 22ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo using TaskId = uint64_t; 23ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo 24ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo // The kNullEventId is reserved for an invalid task and will never be used 25ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo // to refer to a real task. 26ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo static const TaskId kTaskIdNull; 27ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo 28000726053bddc605a6c78b5dece37bcb2c67f291Alex Deymo // Return the MessageLoop for the current thread. It is a fatal error to 29000726053bddc605a6c78b5dece37bcb2c67f291Alex Deymo // request the current MessageLoop if SetAsCurrent() was not called on the 30000726053bddc605a6c78b5dece37bcb2c67f291Alex Deymo // current thread. If you really need to, use ThreadHasCurrent() to check if 31000726053bddc605a6c78b5dece37bcb2c67f291Alex Deymo // there is a current thread. 32ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo static MessageLoop* current(); 33ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo 34000726053bddc605a6c78b5dece37bcb2c67f291Alex Deymo // Return whether there is a MessageLoop in the current thread. 35000726053bddc605a6c78b5dece37bcb2c67f291Alex Deymo static bool ThreadHasCurrent(); 36000726053bddc605a6c78b5dece37bcb2c67f291Alex Deymo 37ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo // Set this message loop as the current thread main loop. Only one message 38ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo // loop can be set at a time. Use ReleaseFromCurrent() to release it. 39ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo void SetAsCurrent(); 40ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo 41ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo // Release this instance from the current thread. This instance must have 42ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo // been previously set with SetAsCurrent(). 43ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo void ReleaseFromCurrent(); 44ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo 45ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo // Schedule a Closure |task| to be executed after a |delay|. Returns a task 46ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo // identifier for the scheduled task that can be used to cancel the task 47ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo // before it is fired by passing it to CancelTask(). 48ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo // In case of an error scheduling the task, the kTaskIdNull is returned. 49ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo // Note that once the call is executed or canceled, the TaskId could be reused 50ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo // at a later point. 51ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo // This methond can only be called from the same thread running the main loop. 52106edd138a59b2fa3856028baa15201d4f7f3ffdAlex Deymo virtual TaskId PostDelayedTask(const tracked_objects::Location& from_here, 53a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo const base::Closure& task, 54ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo base::TimeDelta delay) = 0; 55106edd138a59b2fa3856028baa15201d4f7f3ffdAlex Deymo // Variant without the Location for easier usage. 569ed0cab99f18acb3570a35e9408f24355f6b8324Alex Vakulenko TaskId PostDelayedTask(const base::Closure& task, base::TimeDelta delay) { 57106edd138a59b2fa3856028baa15201d4f7f3ffdAlex Deymo return PostDelayedTask(tracked_objects::Location(), task, delay); 58106edd138a59b2fa3856028baa15201d4f7f3ffdAlex Deymo } 59ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo 60ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo // A convenience method to schedule a call with no delay. 61ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo // This methond can only be called from the same thread running the main loop. 62a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo TaskId PostTask(const base::Closure& task) { 63ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo return PostDelayedTask(task, base::TimeDelta()); 64ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo } 65106edd138a59b2fa3856028baa15201d4f7f3ffdAlex Deymo TaskId PostTask(const tracked_objects::Location& from_here, 66a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo const base::Closure& task) { 67106edd138a59b2fa3856028baa15201d4f7f3ffdAlex Deymo return PostDelayedTask(from_here, task, base::TimeDelta()); 68106edd138a59b2fa3856028baa15201d4f7f3ffdAlex Deymo } 69ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo 703845c6dfdf6c1edb45271e691990c12ef92f77c7Alex Deymo // Watch mode flag used to watch for file descriptors. 713845c6dfdf6c1edb45271e691990c12ef92f77c7Alex Deymo enum WatchMode { 723845c6dfdf6c1edb45271e691990c12ef92f77c7Alex Deymo kWatchRead, 733845c6dfdf6c1edb45271e691990c12ef92f77c7Alex Deymo kWatchWrite, 743845c6dfdf6c1edb45271e691990c12ef92f77c7Alex Deymo }; 753845c6dfdf6c1edb45271e691990c12ef92f77c7Alex Deymo 763845c6dfdf6c1edb45271e691990c12ef92f77c7Alex Deymo // Watch a file descriptor |fd| for it to be ready to perform the operation 773845c6dfdf6c1edb45271e691990c12ef92f77c7Alex Deymo // passed in |mode| without blocking. When that happens, the |task| closure 783845c6dfdf6c1edb45271e691990c12ef92f77c7Alex Deymo // will be executed. If |persistent| is true, the file descriptor will 793845c6dfdf6c1edb45271e691990c12ef92f77c7Alex Deymo // continue to be watched and |task| will continue to be called until the task 803845c6dfdf6c1edb45271e691990c12ef92f77c7Alex Deymo // is canceled with CancelTask(). 813845c6dfdf6c1edb45271e691990c12ef92f77c7Alex Deymo // Returns the TaskId describing this task. In case of error, returns 823845c6dfdf6c1edb45271e691990c12ef92f77c7Alex Deymo // kTaskIdNull. 833845c6dfdf6c1edb45271e691990c12ef92f77c7Alex Deymo virtual TaskId WatchFileDescriptor(const tracked_objects::Location& from_here, 843845c6dfdf6c1edb45271e691990c12ef92f77c7Alex Deymo int fd, 853845c6dfdf6c1edb45271e691990c12ef92f77c7Alex Deymo WatchMode mode, 863845c6dfdf6c1edb45271e691990c12ef92f77c7Alex Deymo bool persistent, 87a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo const base::Closure& task) = 0; 883845c6dfdf6c1edb45271e691990c12ef92f77c7Alex Deymo 893845c6dfdf6c1edb45271e691990c12ef92f77c7Alex Deymo // Convenience function to call WatchFileDescriptor() without a location. 903845c6dfdf6c1edb45271e691990c12ef92f77c7Alex Deymo TaskId WatchFileDescriptor(int fd, 913845c6dfdf6c1edb45271e691990c12ef92f77c7Alex Deymo WatchMode mode, 923845c6dfdf6c1edb45271e691990c12ef92f77c7Alex Deymo bool persistent, 93a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo const base::Closure& task) { 943845c6dfdf6c1edb45271e691990c12ef92f77c7Alex Deymo return WatchFileDescriptor( 953845c6dfdf6c1edb45271e691990c12ef92f77c7Alex Deymo tracked_objects::Location(), fd, mode, persistent, task); 963845c6dfdf6c1edb45271e691990c12ef92f77c7Alex Deymo } 973845c6dfdf6c1edb45271e691990c12ef92f77c7Alex Deymo 98ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo // Cancel a scheduled task. Returns whether the task was canceled. For 99ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo // example, if the callback was already executed (or is being executed) or was 100ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo // already canceled this method will fail. Note that the TaskId can be reused 101ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo // after it was executed or cancelled. 102ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo virtual bool CancelTask(TaskId task_id) = 0; 103ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo 104ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo // --------------------------------------------------------------------------- 105ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo // Methods used to run and stop the message loop. 106ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo 107ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo // Run one iteration of the message loop, dispatching up to one task. The 108ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo // |may_block| tells whether this method is allowed to block waiting for a 109ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo // task to be ready to run. Returns whether it ran a task. Note that even 110ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo // if |may_block| is true, this method can return false immediately if there 111ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo // are no more tasks registered. 112ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo virtual bool RunOnce(bool may_block) = 0; 113ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo 114ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo // Run the main loop until there are no more registered tasks. 115ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo virtual void Run(); 116ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo 117ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo // Quit the running main loop immediately. This method will make the current 118ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo // running Run() method to return right after the current task returns back 119ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo // to the message loop without processing any other task. 120ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo virtual void BreakLoop(); 121ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo 122ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo protected: 123ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo MessageLoop() = default; 124ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo 125ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo private: 126ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo // Tells whether Run() should quit the message loop in the default 127ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo // implementation. 128ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo bool should_exit_ = false; 129ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo 130ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo DISALLOW_COPY_AND_ASSIGN(MessageLoop); 131ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo}; 132ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo 1339ed0cab99f18acb3570a35e9408f24355f6b8324Alex Vakulenko} // namespace brillo 134ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo 135fed60b0c640828b320f56293c8bebc43fd2b1da8Alex Vakulenko#endif // LIBBRILLO_BRILLO_MESSAGE_LOOPS_MESSAGE_LOOP_H_ 136