| // Copyright (c) 2012 The Chromium 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 BASE_MESSAGE_LOOP_MESSAGE_LOOP_TASK_RUNNER_H_ |
| #define BASE_MESSAGE_LOOP_MESSAGE_LOOP_TASK_RUNNER_H_ |
| |
| #include "base/atomicops.h" |
| #include "base/base_export.h" |
| #include "base/callback.h" |
| #include "base/macros.h" |
| #include "base/memory/ref_counted.h" |
| #include "base/message_loop/sequenced_task_source.h" |
| #include "base/pending_task.h" |
| #include "base/single_thread_task_runner.h" |
| #include "base/synchronization/lock.h" |
| #include "base/threading/platform_thread.h" |
| #include "base/time/time.h" |
| |
| namespace base { |
| namespace internal { |
| |
| // A SingleThreadTaskRunner which receives and queues tasks destined to its |
| // owning MessageLoop. It does not manage delays (i.e. tasks returned by |
| // TakeTask() might have a non-zero delay). |
| class BASE_EXPORT MessageLoopTaskRunner : public SingleThreadTaskRunner, |
| public SequencedTaskSource { |
| public: |
| // Constructs a MessageLoopTaskRunner which will notify |task_source_observer| |
| // about tasks it receives. |task_source_observer| will be bound to this |
| // MessageLoopTaskRunner's lifetime. Ownership is required as opposed to a raw |
| // pointer since MessageLoopTaskRunner impls tend to receive tasks beyond the |
| // destination's lifetime. For the same reasons, |task_source_observer| needs |
| // to support being invoked racily during shutdown. |
| MessageLoopTaskRunner( |
| std::unique_ptr<SequencedTaskSource::Observer> task_source_observer); |
| |
| // Initialize this MessageLoopTaskRunner on the current thread. |
| void BindToCurrentThread(); |
| |
| // Instructs this task runner to stop accepting tasks, this cannot be undone. |
| // Note that the registered SequencedTaskSource::Observer may still racily |
| // receive a few DidQueueTask() calls while the Shutdown() signal propagates |
| // to other threads and it needs to support that. |
| void Shutdown(); |
| |
| // SingleThreadTaskRunner: |
| bool PostDelayedTask(const Location& from_here, |
| OnceClosure task, |
| TimeDelta delay) override; |
| bool PostNonNestableDelayedTask(const Location& from_here, |
| OnceClosure task, |
| TimeDelta delay) override; |
| bool RunsTasksInCurrentSequence() const override; |
| |
| // SequencedTaskSource: |
| PendingTask TakeTask() override; |
| bool HasTasks() override; |
| void InjectTask(OnceClosure task) override; |
| |
| // When this functionality is enabled, AddToIncomingQueue() will also add the |
| // queue time to the task. |
| void SetAddQueueTimeToTasks(bool enable); |
| |
| private: |
| friend class RefCountedThreadSafe<MessageLoopTaskRunner>; |
| ~MessageLoopTaskRunner() override; |
| |
| // Appends a task to the incoming queue. Thread-safe. |
| // Returns true if the task was successfully added to the queue. |
| bool AddToIncomingQueue(const Location& from_here, |
| OnceClosure task, |
| TimeDelta delay, |
| Nestable nestable); |
| |
| // ID of the thread |this| was created on. Could be accessed on multiple |
| // threads, protected by |valid_thread_id_lock_|. |
| PlatformThreadId valid_thread_id_ = kInvalidThreadId; |
| mutable Lock valid_thread_id_lock_; |
| |
| std::unique_ptr<SequencedTaskSource::Observer> task_source_observer_; |
| |
| // Tasks to be returned to TakeTask(). Reloaded from |incoming_queue_| when |
| // it becomes empty. |
| TaskQueue outgoing_queue_; |
| |
| // Synchronizes access to all members below this line. |
| base::Lock incoming_queue_lock_; |
| |
| // An incoming queue of tasks that are acquired under a mutex for processing |
| // on this instance's thread. These tasks have not yet been been pushed to |
| // |outgoing_queue_|. |
| TaskQueue incoming_queue_; |
| |
| // True if the |outgoing_queue_| is empty. Toggled under |
| // |incoming_queue_lock_| when reloading the work queue so that |
| // PostPendingTaskLockRequired() can tell, without accessing the thread unsafe |
| // |outgoing_queue_|, if this SequencedTaskSource has been made non-empty by a |
| // PostTask() (and needs to inform its Observer). |
| bool outgoing_queue_empty_ = true; |
| |
| // True if new tasks should be accepted. |
| bool accept_new_tasks_ = true; |
| |
| // The next sequence number to use for delayed tasks. |
| int next_sequence_num_ = 0; |
| |
| // Whether to add the queue time to tasks. |
| base::subtle::Atomic32 add_queue_time_to_tasks_ = 0; |
| |
| DISALLOW_COPY_AND_ASSIGN(MessageLoopTaskRunner); |
| }; |
| |
| } // namespace internal |
| } // namespace base |
| |
| #endif // BASE_MESSAGE_LOOP_MESSAGE_LOOP_TASK_RUNNER_H_ |