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

Side by Side Diff: base/task_scheduler/scheduler_lock.cc

Issue 1698183005: Reference CL for the new task scheduler. (Closed) Base URL: https://luckyluke-private.googlesource.com/src@bigmaster2
Patch Set: Created 4 years, 10 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
« no previous file with comments | « base/task_scheduler/scheduler_lock.h ('k') | base/task_scheduler/scheduler_lock_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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
3 // found in the LICENSE file.
4
5 #include "base/task_scheduler/scheduler_lock.h"
6
7 #include <algorithm>
8 #include <unordered_map>
9 #include <vector>
10
11 #include "base/logging.h"
12 #include "base/memory/singleton.h"
13 #include "base/threading/platform_thread.h"
14
15 #if DCHECK_IS_ON()
16 #define DCHECK_ON_ONLY(statement) statement
17 #else
18 #define DCHECK_ON_ONLY(statement)
19 #endif
20
21 namespace base {
22 namespace internal {
23
24 namespace {
25
26 class SafeAcquisitionTracker {
27 public:
28 static SafeAcquisitionTracker* GetInstance() {
29 return base::Singleton<SafeAcquisitionTracker>::get();
30 }
31
32 void RegisterLock(
33 const SchedulerLock* const lock,
34 const SchedulerLock* const predecessor) {
35 // Reentrant locks are unexpected.
36 CHECK(lock != predecessor);
37 AutoLock auto_lock(metadata_lock_);
38 allowed_predecessors_[lock] = predecessor;
39 AssertSafePredecessor(lock);
40 }
41
42 void UnregisterLock(const SchedulerLock* const lock) {
43 AutoLock auto_lock(metadata_lock_);
44 allowed_predecessors_.erase(lock);
45 }
46
47 void RecordAcquisition(const SchedulerLock* const lock) {
48 AutoLock auto_lock(metadata_lock_);
49 const PlatformThreadId id = PlatformThread::CurrentId();
50 AssertSafeAcquire(id, lock);
51 LockVector& thread_locks = acquired_locks_[id];
52 thread_locks.push_back(lock);
53 }
54
55 void RecordRelease(const SchedulerLock* const lock) {
56 AutoLock auto_lock(metadata_lock_);
57 const PlatformThreadId id = PlatformThread::CurrentId();
58 LockVector& thread_locks = acquired_locks_[id];
59 const auto iter =
60 std::find(thread_locks.begin(), thread_locks.end(), lock);
61 DCHECK(iter != thread_locks.end());
62 thread_locks.erase(iter);
63 }
64
65 private:
66 friend struct base::DefaultSingletonTraits<SafeAcquisitionTracker>;
67 using LockVector = std::vector<const SchedulerLock*>;
68 using PredecessorMap = std::unordered_map<
69 const SchedulerLock*, const SchedulerLock*>;
70 using AcquisitionMap =
71 std::unordered_map<base::PlatformThreadId, LockVector>;
72
73 SafeAcquisitionTracker() = default;
74
75 void AssertSafeAcquire(PlatformThreadId id, const SchedulerLock* const lock) {
76 metadata_lock_.AssertAcquired();
77 const LockVector& thread_locks = acquired_locks_[id];
78
79 // If the thread hasn't ever acquired a lock, this is inherently safe.
80 if (thread_locks.empty())
81 return;
82
83 // Otherwise, make sure that the previous lock acquired is an allowed
84 // predecessor.
85 const SchedulerLock* allowed_predecessor = allowed_predecessors_[lock];
86 DCHECK(thread_locks.back() == allowed_predecessor);
87 }
88
89 void AssertSafePredecessor(const SchedulerLock* lock) {
90 metadata_lock_.AssertAcquired();
91 for (const SchedulerLock* predecessor = allowed_predecessors_[lock];
92 predecessor != nullptr;
93 predecessor = allowed_predecessors_[predecessor]) {
94 if (predecessor == lock)
95 NOTREACHED();
96 }
97 }
98
99 // Synchronizes everything in SafeAcquisitionTracker.
100 base::Lock metadata_lock_;
101
102 PredecessorMap allowed_predecessors_;
103 AcquisitionMap acquired_locks_;
104
105 DISALLOW_COPY_AND_ASSIGN(SafeAcquisitionTracker);
106 };
107
108 } // namespace
109
110 SchedulerLock::SchedulerLock() : SchedulerLock(nullptr) {}
111
112 SchedulerLock::SchedulerLock(const SchedulerLock* predecessor) {
113 DCHECK_ON_ONLY(
114 SafeAcquisitionTracker::GetInstance()->RegisterLock(this, predecessor));
115 }
116
117 SchedulerLock::~SchedulerLock() {
118 DCHECK_ON_ONLY(SafeAcquisitionTracker::GetInstance()->UnregisterLock(this));
119 }
120
121 void SchedulerLock::Acquire() {
122 lock_.Acquire();
123 DCHECK_ON_ONLY(
124 SafeAcquisitionTracker::GetInstance()->RecordAcquisition(this));
125 }
126
127 void SchedulerLock::Release() {
128 lock_.Release();
129 DCHECK_ON_ONLY(SafeAcquisitionTracker::GetInstance()->RecordRelease(this));
130 }
131
132 Lock* SchedulerLock::RawLockForConditionVariable() {
133 return &lock_;
134 }
135
136 } // namespace internal
137 } // base
OLDNEW
« no previous file with comments | « base/task_scheduler/scheduler_lock.h ('k') | base/task_scheduler/scheduler_lock_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698