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

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

Issue 1706123002: TaskScheduler [2/9] Scheduler Lock (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
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
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_impl.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/synchronization/condition_variable.h"
14 #include "base/threading/platform_thread.h"
15
16 namespace base {
17 namespace internal {
18
19 namespace {
20
21 class SafeAcquisitionTracker {
22 public:
23 static SafeAcquisitionTracker* GetInstance() {
24 return base::Singleton<SafeAcquisitionTracker>::get();
gab 2016/02/18 16:58:06 Instead of a Singleton, can we use a LazyInstance:
robliao 2016/02/18 21:59:37 Works for me. Done.
25 }
26
27 void RegisterLock(
28 const SchedulerLockImpl* const lock,
29 const SchedulerLockImpl* const predecessor) {
30 // Reentrant locks are unexpected.
gab 2016/02/18 16:58:06 s/unexpected/unsupported/
robliao 2016/02/18 21:59:37 Done.
31 CHECK(lock != predecessor);
gab 2016/02/18 16:58:06 DCHECK (equivalent since this code ever runs in
robliao 2016/02/18 21:59:37 Done.
32 AutoLock auto_lock(metadata_lock_);
33 allowed_predecessors_[lock] = predecessor;
34 AssertSafePredecessor(lock);
35 }
36
37 void UnregisterLock(const SchedulerLockImpl* const lock) {
38 AutoLock auto_lock(metadata_lock_);
39 allowed_predecessors_.erase(lock);
40 }
41
42 void RecordAcquisition(const SchedulerLockImpl* const lock) {
43 AutoLock auto_lock(metadata_lock_);
44 const PlatformThreadId id = PlatformThread::CurrentId();
45 AssertSafeAcquire(id, lock);
46 LockVector& thread_locks = acquired_locks_[id];
47 thread_locks.push_back(lock);
gab 2016/02/18 16:58:06 Merge above two lines into: acquired_locks_[id].p
robliao 2016/02/18 21:59:37 Symmetry is nice, but it's still the same code. Me
48 }
49
50 void RecordRelease(const SchedulerLockImpl* const lock) {
51 AutoLock auto_lock(metadata_lock_);
52 const PlatformThreadId id = PlatformThread::CurrentId();
53 LockVector& thread_locks = acquired_locks_[id];
54 const auto iter =
55 std::find(thread_locks.begin(), thread_locks.end(), lock);
56 DCHECK(iter != thread_locks.end());
57 thread_locks.erase(iter);
58 }
59
60 private:
61 friend struct base::DefaultSingletonTraits<SafeAcquisitionTracker>;
62 using LockVector = std::vector<const SchedulerLockImpl*>;
63 using PredecessorMap = std::unordered_map<
64 const SchedulerLockImpl*, const SchedulerLockImpl*>;
65 using AcquisitionMap =
66 std::unordered_map<base::PlatformThreadId, LockVector>;
gab 2016/02/18 16:58:06 How about using ThreadLocalStorage here instead of
robliao 2016/02/18 21:59:37 We would only be able to save on the release. Acqu
gab 2016/02/19 16:08:02 To avoid this being a "gotcha -- only lock here no
gab 2016/02/19 22:05:24 ping ^^
robliao 2016/02/19 23:51:11 Oops. Missed this one. Done.
67
68 SafeAcquisitionTracker() = default;
69
70 void AssertSafeAcquire(PlatformThreadId id,
gab 2016/02/18 16:58:06 Add a comment + mention that this must be called b
robliao 2016/02/18 21:59:37 This keeps both RecordAcquisition and RecordReleas
71 const SchedulerLockImpl* const lock) {
72 metadata_lock_.AssertAcquired();
73 const LockVector& thread_locks = acquired_locks_[id];
74
75 // If the thread hasn't ever acquired a lock, this is inherently safe.
gab 2016/02/18 16:58:06 // If the thread doesn't currently own a lock, thi
robliao 2016/02/18 21:59:37 Fixed.
76 if (thread_locks.empty())
77 return;
78
79 // Otherwise, make sure that the previous lock acquired is an allowed
80 // predecessor.
81 const SchedulerLockImpl* allowed_predecessor =
82 allowed_predecessors_[lock];
83 DCHECK(thread_locks.back() == allowed_predecessor);
84 }
85
86 void AssertSafePredecessor(const SchedulerLockImpl* lock) {
87 metadata_lock_.AssertAcquired();
88 for (const SchedulerLockImpl* predecessor = allowed_predecessors_[lock];
89 predecessor != nullptr;
90 predecessor = allowed_predecessors_[predecessor]) {
91 if (predecessor == lock)
92 NOTREACHED();
gab 2016/02/18 16:58:06 So is this method only verifying that we do not ge
robliao 2016/02/18 21:59:37 There's actually a unit test for this :-). It is i
93 }
94 }
95
96 // Synchronizes everything in SafeAcquisitionTracker.
97 base::Lock metadata_lock_;
98
99 PredecessorMap allowed_predecessors_;
gab 2016/02/18 16:58:07 Whenever I saw this in code the plural form made m
robliao 2016/02/18 21:59:37 Went with allowed_predecessor_map.
100 AcquisitionMap acquired_locks_;
101
102 DISALLOW_COPY_AND_ASSIGN(SafeAcquisitionTracker);
103 };
104
105 } // namespace
106
107 SchedulerLockImpl::SchedulerLockImpl() : SchedulerLockImpl(nullptr) {}
gab 2016/02/18 16:58:06 Seems this will call RegisterLock with a nullptr p
robliao 2016/02/18 21:59:37 In invariant here is that all locks are registered
108
109 SchedulerLockImpl::SchedulerLockImpl(const SchedulerLockImpl* predecessor) {
110 SafeAcquisitionTracker::GetInstance()->RegisterLock(this, predecessor);
111 }
112
113 SchedulerLockImpl::~SchedulerLockImpl() {
114 SafeAcquisitionTracker::GetInstance()->UnregisterLock(this);
115 }
116
117 void SchedulerLockImpl::Acquire() {
118 lock_.Acquire();
119 SafeAcquisitionTracker::GetInstance()->RecordAcquisition(this);
120 }
121
122 void SchedulerLockImpl::Release() {
123 lock_.Release();
124 SafeAcquisitionTracker::GetInstance()->RecordRelease(this);
125 }
126
127 scoped_ptr<ConditionVariable> SchedulerLockImpl::CreateConditionVariable() {
128 return scoped_ptr<ConditionVariable>(new ConditionVariable(&lock_));
129 }
130
131 } // namespace internal
132 } // base
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698