Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(246)

Side by Side Diff: base/task_scheduler/scheduler_worker.h

Issue 2044023003: Virtualize The Existence of a Scheduler Worker Thread (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@detach
Patch Set: Apply Renames Created 4 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2016 The Chromium Authors. All rights reserved. 1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #ifndef BASE_TASK_SCHEDULER_SCHEDULER_WORKER_H_ 5 #ifndef BASE_TASK_SCHEDULER_SCHEDULER_WORKER_H_
6 #define BASE_TASK_SCHEDULER_SCHEDULER_WORKER_H_ 6 #define BASE_TASK_SCHEDULER_SCHEDULER_WORKER_H_
7 7
8 #include <memory> 8 #include <memory>
9 9
10 #include "base/base_export.h" 10 #include "base/base_export.h"
11 #include "base/macros.h" 11 #include "base/macros.h"
12 #include "base/memory/ref_counted.h" 12 #include "base/memory/ref_counted.h"
13 #include "base/synchronization/waitable_event.h" 13 #include "base/synchronization/waitable_event.h"
14 #include "base/task_scheduler/scheduler_lock.h" 14 #include "base/task_scheduler/scheduler_lock.h"
15 #include "base/task_scheduler/sequence.h" 15 #include "base/task_scheduler/sequence.h"
16 #include "base/threading/platform_thread.h" 16 #include "base/threading/platform_thread.h"
17 #include "base/time/time.h" 17 #include "base/time/time.h"
18 18
19 namespace base { 19 namespace base {
20 namespace internal { 20 namespace internal {
21 21
22 class TaskTracker; 22 class TaskTracker;
23 23
24 // A thread that runs Tasks from Sequences returned by a delegate. 24 // A worker that manages a single thread to run Tasks from Sequences returned
25 // by a delegate.
25 // 26 //
26 // A SchedulerWorker starts out sleeping. It is woken up by a call to WakeUp(). 27 // A SchedulerWorker starts out sleeping. It is woken up by a call to WakeUp().
27 // After a wake-up, a SchedulerWorker runs Tasks from Sequences returned by the 28 // After a wake-up, a SchedulerWorker runs Tasks from Sequences returned by the
28 // GetWork() method of its delegate as long as it doesn't return nullptr. It 29 // GetWork() method of its delegate as long as it doesn't return nullptr. It
29 // also periodically checks with its TaskTracker whether shutdown has completed 30 // also periodically checks with its TaskTracker whether shutdown has completed
30 // and exits when it has. 31 // and exits when it has.
31 // 32 //
33 // The worker is free to release and reallocate the platform thread with
34 // guidance from the delegate.
35 //
32 // This class is thread-safe. 36 // This class is thread-safe.
33 class BASE_EXPORT SchedulerWorker : public PlatformThread::Delegate { 37 class BASE_EXPORT SchedulerWorker {
34 public: 38 public:
35 // Delegate interface for SchedulerWorker. The methods are always called from 39 // Delegate interface for SchedulerWorker. The methods are always called from
36 // a thread managed by the SchedulerWorker instance. 40 // a thread managed by the SchedulerWorker instance.
37 class Delegate { 41 class Delegate {
38 public: 42 public:
39 virtual ~Delegate() = default; 43 virtual ~Delegate() = default;
40 44
41 // Called by a thread managed by |worker| when it enters its main function. 45 // Called by a thread managed by |worker| when it enters its main function.
46 // If a thread is recreated after detachment, this call will occur again.
42 virtual void OnMainEntry(SchedulerWorker* worker) = 0; 47 virtual void OnMainEntry(SchedulerWorker* worker) = 0;
43 48
44 // Called by a thread managed by |worker| to get a Sequence from which to 49 // Called by a thread managed by |worker| to get a Sequence from which to
45 // run a Task. 50 // run a Task.
46 virtual scoped_refptr<Sequence> GetWork(SchedulerWorker* worker) = 0; 51 virtual scoped_refptr<Sequence> GetWork(SchedulerWorker* worker) = 0;
47 52
48 // Called when |sequence| isn't empty after the SchedulerWorker pops a Task 53 // Called when |sequence| isn't empty after the SchedulerWorker pops a Task
49 // from it. |sequence| is the last Sequence returned by GetWork(). 54 // from it. |sequence| is the last Sequence returned by GetWork().
50 virtual void ReEnqueueSequence(scoped_refptr<Sequence> sequence) = 0; 55 virtual void ReEnqueueSequence(scoped_refptr<Sequence> sequence) = 0;
51 56
52 // Called by a thread to determine how long to sleep before the next call to 57 // Called by a thread to determine how long to sleep before the next call to
53 // GetWork(). GetWork() may be called before this timeout expires if the 58 // GetWork(). GetWork() may be called before this timeout expires if the
54 // worker's WakeUp() method is called. 59 // worker's WakeUp() method is called.
55 virtual TimeDelta GetSleepTimeout() = 0; 60 virtual TimeDelta GetSleepTimeout() = 0;
61
62 // Called by a thread if it is allowed to detach if the last call to
63 // GetWork() returned nullptr.
64 //
65 // It is the responsibility of the delegate to determine if detachment is
66 // safe. If the delegate is responsible for thread-affine work, detachment
67 // is generally not safe.
68 //
69 // When true is returned:
70 // - The next WakeUp() could be more costly due to new thread creation.
71 // - The worker will take this as a signal that it can detach, but it is not
72 // obligated to do so.
73 // This MUST return false if SchedulerWorker::JoinForTesting() is in
74 // progress.
75 virtual bool CanDetach(SchedulerWorker* worker) = 0;
56 }; 76 };
57 77
78 enum class InitialState { ALIVE, DETACHED };
79
58 // Creates a SchedulerWorker with priority |thread_priority| that runs Tasks 80 // Creates a SchedulerWorker with priority |thread_priority| that runs Tasks
59 // from Sequences returned by |delegate|. |task_tracker| is used to handle 81 // from Sequences returned by |delegate|. |task_tracker| is used to handle
60 // shutdown behavior of Tasks. Returns nullptr if creating the underlying 82 // shutdown behavior of Tasks. If |worker_state| is DETACHED, the worker will
fdoray 2016/06/22 18:22:43 the *thread* will
robliao 2016/06/22 19:24:33 Done.
61 // platform thread fails. 83 // be created upon a WakeUp. Returns nullptr if creating the underlying
fdoray 2016/06/22 18:22:43 WakeUp*()* ? () are used in comments in this file
robliao 2016/06/22 19:24:33 Done.
84 // platform thread fails during Create.
fdoray 2016/06/22 18:22:43 Create*()*?
robliao 2016/06/22 19:24:33 Done.
62 static std::unique_ptr<SchedulerWorker> Create( 85 static std::unique_ptr<SchedulerWorker> Create(
63 ThreadPriority thread_priority, 86 ThreadPriority thread_priority,
64 std::unique_ptr<Delegate> delegate, 87 std::unique_ptr<Delegate> delegate,
65 TaskTracker* task_tracker); 88 TaskTracker* task_tracker,
89 InitialState initial_state);
66 90
67 // Destroying a SchedulerWorker in production is not allowed; it is always 91 // Destroying a SchedulerWorker in production is not allowed; it is always
68 // leaked. In tests, it can only be destroyed after JoinForTesting() has 92 // leaked. In tests, it can only be destroyed after JoinForTesting() has
69 // returned. 93 // returned.
70 ~SchedulerWorker() override; 94 ~SchedulerWorker();
71 95
72 // Wakes up this SchedulerWorker if it wasn't already awake. After this 96 // Wakes up this SchedulerWorker if it wasn't already awake. After this
73 // is called, this SchedulerWorker will run Tasks from Sequences 97 // is called, this SchedulerWorker will run Tasks from Sequences
74 // returned by the GetWork() method of its delegate until it returns nullptr. 98 // returned by the GetWork() method of its delegate until it returns nullptr.
99 // WakeUp may fail if the worker is detached and it fails to allocate a new
fdoray 2016/06/22 18:22:43 WakeUp*()*?
robliao 2016/06/22 19:24:33 Done.
100 // worker. If this happens, there will be no call to GetWork().
75 void WakeUp(); 101 void WakeUp();
76 102
77 SchedulerWorker::Delegate* delegate() { return delegate_.get(); } 103 SchedulerWorker::Delegate* delegate() { return delegate_.get(); }
78 104
79 // Joins this SchedulerWorker. If a Task is already running, it will be 105 // Joins this SchedulerWorker. If a Task is already running, it will be
80 // allowed to complete its execution. This can only be called once. 106 // allowed to complete its execution. This can only be called once.
81 void JoinForTesting(); 107 void JoinForTesting();
82 108
109 // Returns true if the worker is alive.
110 bool ThreadAliveForTesting() const;
111
83 private: 112 private:
113 class Thread;
114
84 SchedulerWorker(ThreadPriority thread_priority, 115 SchedulerWorker(ThreadPriority thread_priority,
85 std::unique_ptr<Delegate> delegate, 116 std::unique_ptr<Delegate> delegate,
86 TaskTracker* task_tracker); 117 TaskTracker* task_tracker);
87 118
88 // PlatformThread::Delegate: 119 // Returns the thread instance if the detach was successful so that it can be
89 void ThreadMain() override; 120 // freed upon termination of the thread.
121 // If the detach is not possible, returns nullptr.
122 std::unique_ptr<SchedulerWorker::Thread> Detach();
123
124 void CreateThread();
125
126 void CreateThreadAssertSynchronized();
90 127
91 bool ShouldExitForTesting() const; 128 bool ShouldExitForTesting() const;
92 129
93 // Platform thread managed by this SchedulerWorker. 130 // Synchronizes access to |thread_|
94 PlatformThreadHandle thread_handle_; 131 mutable SchedulerLock thread_lock_;
95 132
96 // Event signaled to wake up this SchedulerWorker. 133 // The underlying thread for this SchedulerWorker.
97 WaitableEvent wake_up_event_; 134 std::unique_ptr<Thread> thread_;
98 135
136 const ThreadPriority thread_priority_;
99 const std::unique_ptr<Delegate> delegate_; 137 const std::unique_ptr<Delegate> delegate_;
100 TaskTracker* const task_tracker_; 138 TaskTracker* const task_tracker_;
101 139
102 // Synchronizes access to |should_exit_for_testing_|. 140 // Synchronizes access to |should_exit_for_testing_|.
103 mutable SchedulerLock should_exit_for_testing_lock_; 141 mutable SchedulerLock should_exit_for_testing_lock_;
104 142
105 // True once JoinForTesting() has been called. 143 // True once JoinForTesting() has been called.
106 bool should_exit_for_testing_ = false; 144 bool should_exit_for_testing_ = false;
107 145
108 DISALLOW_COPY_AND_ASSIGN(SchedulerWorker); 146 DISALLOW_COPY_AND_ASSIGN(SchedulerWorker);
109 }; 147 };
110 148
111 } // namespace internal 149 } // namespace internal
112 } // namespace base 150 } // namespace base
113 151
114 #endif // BASE_TASK_SCHEDULER_SCHEDULER_WORKER_H_ 152 #endif // BASE_TASK_SCHEDULER_SCHEDULER_WORKER_H_
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698