123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243 |
- // Copyright 2016 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_TASK_THREAD_POOL_WORKER_THREAD_H_
- #define BASE_TASK_THREAD_POOL_WORKER_THREAD_H_
- #include <memory>
- #include "base/base_export.h"
- #include "base/macros.h"
- #include "base/memory/ref_counted.h"
- #include "base/synchronization/atomic_flag.h"
- #include "base/synchronization/waitable_event.h"
- #include "base/task/common/checked_lock.h"
- #include "base/task/thread_pool/task_source.h"
- #include "base/task/thread_pool/tracked_ref.h"
- #include "base/thread_annotations.h"
- #include "base/threading/platform_thread.h"
- #include "base/time/time.h"
- #include "build/build_config.h"
- namespace base {
- class WorkerThreadObserver;
- namespace internal {
- class TaskTracker;
- // A worker that manages a single thread to run Tasks from TaskSources returned
- // by a delegate.
- //
- // A WorkerThread starts out sleeping. It is woken up by a call to WakeUp().
- // After a wake-up, a WorkerThread runs Tasks from TaskSources returned by
- // the GetWork() method of its delegate as long as it doesn't return nullptr. It
- // also periodically checks with its TaskTracker whether shutdown has completed
- // and exits when it has.
- //
- // This class is thread-safe.
- class BASE_EXPORT WorkerThread : public RefCountedThreadSafe<WorkerThread>,
- public PlatformThread::Delegate {
- public:
- // Labels this WorkerThread's association. This doesn't affect any logic
- // but will add a stack frame labeling this thread for ease of stack trace
- // identification.
- enum class ThreadLabel {
- POOLED,
- SHARED,
- DEDICATED,
- #if defined(OS_WIN)
- SHARED_COM,
- DEDICATED_COM,
- #endif // defined(OS_WIN)
- };
- // Delegate interface for WorkerThread. All methods are called from the
- // thread managed by the WorkerThread instance.
- class BASE_EXPORT Delegate {
- public:
- virtual ~Delegate() = default;
- // Returns the ThreadLabel the Delegate wants its WorkerThreads' stacks
- // to be labeled with.
- virtual ThreadLabel GetThreadLabel() const = 0;
- // Called by |worker|'s thread when it enters its main function.
- virtual void OnMainEntry(const WorkerThread* worker) = 0;
- // Called by |worker|'s thread to get a TaskSource from which to run a Task.
- virtual RegisteredTaskSource GetWork(WorkerThread* worker) = 0;
- // Called by the WorkerThread after it ran a Task. If the Task's
- // TaskSource should be reenqueued, it is passed to |task_source|.
- // Otherwise, |task_source| is nullptr.
- virtual void DidProcessTask(RegisteredTaskSource task_source) = 0;
- // Called to determine how long to sleep before the next call to GetWork().
- // GetWork() may be called before this timeout expires if the worker's
- // WakeUp() method is called.
- virtual TimeDelta GetSleepTimeout() = 0;
- // Called by the WorkerThread's thread to wait for work. Override this
- // method if the thread in question needs special handling to go to sleep.
- // |wake_up_event| is a manually resettable event and is signaled on
- // WorkerThread::WakeUp()
- virtual void WaitForWork(WaitableEvent* wake_up_event);
- // Called by |worker|'s thread right before the main function exits. The
- // Delegate is free to release any associated resources in this call. It is
- // guaranteed that WorkerThread won't access the Delegate or the
- // TaskTracker after calling OnMainExit() on the Delegate.
- virtual void OnMainExit(WorkerThread* worker) {}
- };
- // Creates a WorkerThread that runs Tasks from TaskSources returned by
- // |delegate|. No actual thread will be created for this WorkerThread
- // before Start() is called. |priority_hint| is the preferred thread priority;
- // the actual thread priority depends on shutdown state and platform
- // capabilities. |task_tracker| is used to handle shutdown behavior of Tasks.
- // |predecessor_lock| is a lock that is allowed to be held when calling
- // methods on this WorkerThread. |backward_compatibility| indicates
- // whether backward compatibility is enabled. Either JoinForTesting() or
- // Cleanup() must be called before releasing the last external reference.
- WorkerThread(ThreadPriority priority_hint,
- std::unique_ptr<Delegate> delegate,
- TrackedRef<TaskTracker> task_tracker,
- const CheckedLock* predecessor_lock = nullptr);
- // Creates a thread to back the WorkerThread. The thread will be in a wait
- // state pending a WakeUp() call. No thread will be created if Cleanup() was
- // called. If specified, |worker_thread_observer| will be notified when the
- // worker enters and exits its main function. It must not be destroyed before
- // JoinForTesting() has returned (must never be destroyed in production).
- // Returns true on success.
- bool Start(WorkerThreadObserver* worker_thread_observer = nullptr);
- // Wakes up this WorkerThread if it wasn't already awake. After this is
- // called, this WorkerThread will run Tasks from TaskSources returned by
- // the GetWork() method of its delegate until it returns nullptr. No-op if
- // Start() wasn't called. DCHECKs if called after Start() has failed or after
- // Cleanup() has been called.
- void WakeUp();
- WorkerThread::Delegate* delegate() { return delegate_.get(); }
- // Joins this WorkerThread. If a Task is already running, it will be
- // allowed to complete its execution. This can only be called once.
- //
- // Note: A thread that detaches before JoinForTesting() is called may still be
- // running after JoinForTesting() returns. However, it can't run tasks after
- // JoinForTesting() returns.
- void JoinForTesting();
- // Returns true if the worker is alive.
- bool ThreadAliveForTesting() const;
- // Makes a request to cleanup the worker. This may be called from any thread.
- // The caller is expected to release its reference to this object after
- // calling Cleanup(). Further method calls after Cleanup() returns are
- // undefined.
- //
- // Expected Usage:
- // scoped_refptr<WorkerThread> worker_ = /* Existing Worker */
- // worker_->Cleanup();
- // worker_ = nullptr;
- void Cleanup();
- // Informs this WorkerThread about periods during which it is not being
- // used. Thread-safe.
- void BeginUnusedPeriod();
- void EndUnusedPeriod();
- // Returns the last time this WorkerThread was used. Returns a null time if
- // this WorkerThread is currently in-use. Thread-safe.
- TimeTicks GetLastUsedTime() const;
- private:
- friend class RefCountedThreadSafe<WorkerThread>;
- class Thread;
- ~WorkerThread() override;
- bool ShouldExit() const;
- // Returns the thread priority to use based on the priority hint, current
- // shutdown state, and platform capabilities.
- ThreadPriority GetDesiredThreadPriority() const;
- // Changes the thread priority to |desired_thread_priority|. Must be called on
- // the thread managed by |this|.
- void UpdateThreadPriority(ThreadPriority desired_thread_priority);
- // PlatformThread::Delegate:
- void ThreadMain() override;
- // Dummy frames to act as "RunLabeledWorker()" (see RunMain() below). Their
- // impl is aliased to prevent compiler/linker from optimizing them out.
- void RunPooledWorker();
- void RunBackgroundPooledWorker();
- void RunSharedWorker();
- void RunBackgroundSharedWorker();
- void RunDedicatedWorker();
- void RunBackgroundDedicatedWorker();
- #if defined(OS_WIN)
- void RunSharedCOMWorker();
- void RunBackgroundSharedCOMWorker();
- void RunDedicatedCOMWorker();
- void RunBackgroundDedicatedCOMWorker();
- #endif // defined(OS_WIN)
- // The real main, invoked through :
- // ThreadMain() -> RunLabeledWorker() -> RunWorker().
- // "RunLabeledWorker()" is a dummy frame based on ThreadLabel+ThreadPriority
- // and used to easily identify threads in stack traces.
- void RunWorker();
- // Self-reference to prevent destruction of |this| while the thread is alive.
- // Set in Start() before creating the thread. Reset in ThreadMain() before the
- // thread exits. No lock required because the first access occurs before the
- // thread is created and the second access occurs on the thread.
- scoped_refptr<WorkerThread> self_;
- mutable CheckedLock thread_lock_;
- // Handle for the thread managed by |this|.
- PlatformThreadHandle thread_handle_ GUARDED_BY(thread_lock_);
- // The last time this worker was used by its owner (e.g. to process work or
- // stand as a required idle thread).
- TimeTicks last_used_time_ GUARDED_BY(thread_lock_);
- // Event to wake up the thread managed by |this|.
- WaitableEvent wake_up_event_{WaitableEvent::ResetPolicy::AUTOMATIC,
- WaitableEvent::InitialState::NOT_SIGNALED};
- // Whether the thread should exit. Set by Cleanup().
- AtomicFlag should_exit_;
- const std::unique_ptr<Delegate> delegate_;
- const TrackedRef<TaskTracker> task_tracker_;
- // Optional observer notified when a worker enters and exits its main
- // function. Set in Start() and never modified afterwards.
- WorkerThreadObserver* worker_thread_observer_ = nullptr;
- // Desired thread priority.
- const ThreadPriority priority_hint_;
- // Actual thread priority. Can be different than |priority_hint_| depending on
- // system capabilities and shutdown state. No lock required because all post-
- // construction accesses occur on the thread.
- ThreadPriority current_thread_priority_;
- // Set once JoinForTesting() has been called.
- AtomicFlag join_called_for_testing_;
- DISALLOW_COPY_AND_ASSIGN(WorkerThread);
- };
- } // namespace internal
- } // namespace base
- #endif // BASE_TASK_THREAD_POOL_WORKER_THREAD_H_
|