C++程序  |  136行  |  5.33 KB

// Copyright 2015 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef LIBBRILLO_BRILLO_MESSAGE_LOOPS_MESSAGE_LOOP_H_
#define LIBBRILLO_BRILLO_MESSAGE_LOOPS_MESSAGE_LOOP_H_

#include <string>

#include <base/callback.h>
#include <base/location.h>
#include <base/time/time.h>
#include <brillo/brillo_export.h>

namespace brillo {

class BRILLO_EXPORT MessageLoop {
 public:
  virtual ~MessageLoop();

  // A unique task identifier used to refer to scheduled callbacks.
  using TaskId = uint64_t;

  // The kNullEventId is reserved for an invalid task and will never be used
  // to refer to a real task.
  static const TaskId kTaskIdNull;

  // Return the MessageLoop for the current thread. It is a fatal error to
  // request the current MessageLoop if SetAsCurrent() was not called on the
  // current thread. If you really need to, use ThreadHasCurrent() to check if
  // there is a current thread.
  static MessageLoop* current();

  // Return whether there is a MessageLoop in the current thread.
  static bool ThreadHasCurrent();

  // Set this message loop as the current thread main loop. Only one message
  // loop can be set at a time. Use ReleaseFromCurrent() to release it.
  void SetAsCurrent();

  // Release this instance from the current thread. This instance must have
  // been previously set with SetAsCurrent().
  void ReleaseFromCurrent();

  // Schedule a Closure |task| to be executed after a |delay|. Returns a task
  // identifier for the scheduled task that can be used to cancel the task
  // before it is fired by passing it to CancelTask().
  // In case of an error scheduling the task, the kTaskIdNull is returned.
  // Note that once the call is executed or canceled, the TaskId could be reused
  // at a later point.
  // This methond can only be called from the same thread running the main loop.
  virtual TaskId PostDelayedTask(const tracked_objects::Location& from_here,
                                 const base::Closure& task,
                                 base::TimeDelta delay) = 0;
  // Variant without the Location for easier usage.
  TaskId PostDelayedTask(const base::Closure& task, base::TimeDelta delay) {
    return PostDelayedTask(tracked_objects::Location(), task, delay);
  }

  // A convenience method to schedule a call with no delay.
  // This methond can only be called from the same thread running the main loop.
  TaskId PostTask(const base::Closure& task) {
    return PostDelayedTask(task, base::TimeDelta());
  }
  TaskId PostTask(const tracked_objects::Location& from_here,
                  const base::Closure& task) {
    return PostDelayedTask(from_here, task, base::TimeDelta());
  }

  // Watch mode flag used to watch for file descriptors.
  enum WatchMode {
    kWatchRead,
    kWatchWrite,
  };

  // Watch a file descriptor |fd| for it to be ready to perform the operation
  // passed in |mode| without blocking. When that happens, the |task| closure
  // will be executed. If |persistent| is true, the file descriptor will
  // continue to be watched and |task| will continue to be called until the task
  // is canceled with CancelTask().
  // Returns the TaskId describing this task. In case of error, returns
  // kTaskIdNull.
  virtual TaskId WatchFileDescriptor(const tracked_objects::Location& from_here,
                                     int fd,
                                     WatchMode mode,
                                     bool persistent,
                                     const base::Closure& task) = 0;

  // Convenience function to call WatchFileDescriptor() without a location.
  TaskId WatchFileDescriptor(int fd,
                             WatchMode mode,
                             bool persistent,
                             const base::Closure& task) {
    return WatchFileDescriptor(
        tracked_objects::Location(), fd, mode, persistent, task);
  }

  // Cancel a scheduled task. Returns whether the task was canceled. For
  // example, if the callback was already executed (or is being executed) or was
  // already canceled this method will fail. Note that the TaskId can be reused
  // after it was executed or cancelled.
  virtual bool CancelTask(TaskId task_id) = 0;

  // ---------------------------------------------------------------------------
  // Methods used to run and stop the message loop.

  // Run one iteration of the message loop, dispatching up to one task. The
  // |may_block| tells whether this method is allowed to block waiting for a
  // task to be ready to run. Returns whether it ran a task. Note that even
  // if |may_block| is true, this method can return false immediately if there
  // are no more tasks registered.
  virtual bool RunOnce(bool may_block) = 0;

  // Run the main loop until there are no more registered tasks.
  virtual void Run();

  // Quit the running main loop immediately. This method will make the current
  // running Run() method to return right after the current task returns back
  // to the message loop without processing any other task.
  virtual void BreakLoop();

 protected:
  MessageLoop() = default;

 private:
  // Tells whether Run() should quit the message loop in the default
  // implementation.
  bool should_exit_ = false;

  DISALLOW_COPY_AND_ASSIGN(MessageLoop);
};

}  // namespace brillo

#endif  // LIBBRILLO_BRILLO_MESSAGE_LOOPS_MESSAGE_LOOP_H_