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

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

Issue 1802003002: DO NOT SUBMIT SchedulerLock - DCHECK Checks (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@schedulerlock
Patch Set: All inlined. Created 4 years, 9 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/lazy_instance.h"
12 #include "base/logging.h"
13 #include "base/synchronization/condition_variable.h"
14 #include "base/threading/platform_thread.h"
15 #include "base/threading/thread_local_storage.h"
16
17 namespace base {
18 namespace internal {
19
20 namespace {
21
22 class SafeAcquisitionTracker {
23 public:
24 SafeAcquisitionTracker() : tls_acquired_locks_(&OnTLSDestroy) {}
25
26 void RegisterLock(
27 const SchedulerLockImpl* const lock,
28 const SchedulerLockImpl* const predecessor) {
29 AutoLock auto_lock(allowed_predecessor_map_lock_);
30 allowed_predecessor_map_[lock] = predecessor;
31 AssertSafePredecessor(lock);
32 }
33
34 void UnregisterLock(const SchedulerLockImpl* const lock) {
35 AutoLock auto_lock(allowed_predecessor_map_lock_);
36 allowed_predecessor_map_.erase(lock);
37 }
38
39 void RecordAcquisition(const SchedulerLockImpl* const lock) {
40 AssertSafeAcquire(lock);
41 GetAcquiredLocksOnCurrentThread()->push_back(lock);
42 }
43
44 void RecordRelease(const SchedulerLockImpl* const lock) {
45 LockVector* acquired_locks = GetAcquiredLocksOnCurrentThread();
46 const auto iter_at_lock =
47 std::find(acquired_locks->begin(), acquired_locks->end(), lock);
48 DCHECK(iter_at_lock != acquired_locks->end());
49 acquired_locks->erase(iter_at_lock);
50 }
51
52 private:
53 using LockVector = std::vector<const SchedulerLockImpl*>;
54 using PredecessorMap = std::unordered_map<
55 const SchedulerLockImpl*, const SchedulerLockImpl*>;
56
57 // This asserts that the lock is safe to acquire. This means that this should
58 // be run before actually recording the acquisition.
59 void AssertSafeAcquire(const SchedulerLockImpl* const lock) {
60 const LockVector* acquired_locks = GetAcquiredLocksOnCurrentThread();
61
62 // If the thread currently holds no locks, this is inherently safe.
63 if (acquired_locks->empty())
64 return;
65
66 // Otherwise, make sure that the previous lock acquired is an allowed
67 // predecessor.
68 }
69
70 void AssertSafePredecessor(const SchedulerLockImpl* lock) const {
71 allowed_predecessor_map_lock_.AssertAcquired();
72 }
73
74 LockVector* GetAcquiredLocksOnCurrentThread() {
75 if (!tls_acquired_locks_.Get())
76 tls_acquired_locks_.Set(new LockVector);
77
78 return reinterpret_cast<LockVector*>(tls_acquired_locks_.Get());
79 }
80
81 static void OnTLSDestroy(void* value) {
82 delete reinterpret_cast<LockVector*>(value);
83 }
84
85 // Synchronizes access to |allowed_predecessor_map_|.
86 Lock allowed_predecessor_map_lock_;
87
88 // A map of allowed predecessors.
89 PredecessorMap allowed_predecessor_map_;
90
91 // A thread-local slot holding a vector of locks currently acquired on the
92 // current thread.
93 ThreadLocalStorage::Slot tls_acquired_locks_;
94
95 DISALLOW_COPY_AND_ASSIGN(SafeAcquisitionTracker);
96 };
97
98 LazyInstance<SafeAcquisitionTracker>::Leaky g_safe_acquisition_tracker =
99 LAZY_INSTANCE_INITIALIZER;
100
101 } // namespace
102
103 SchedulerLockImpl::SchedulerLockImpl() : SchedulerLockImpl(nullptr) {}
104
105 SchedulerLockImpl::SchedulerLockImpl(const SchedulerLockImpl* predecessor) {
106 g_safe_acquisition_tracker.Get().RegisterLock(this, predecessor);
107 }
108
109 SchedulerLockImpl::~SchedulerLockImpl() {
110 g_safe_acquisition_tracker.Get().UnregisterLock(this);
111 }
112
113 void SchedulerLockImpl::Acquire() {
114 lock_.Acquire();
115 g_safe_acquisition_tracker.Get().RecordAcquisition(this);
116 }
117
118 void SchedulerLockImpl::Release() {
119 lock_.Release();
120 g_safe_acquisition_tracker.Get().RecordRelease(this);
121 }
122
123 void SchedulerLockImpl::AssertAcquired() const {
124 lock_.AssertAcquired();
125 }
126
127 scoped_ptr<ConditionVariable> SchedulerLockImpl::CreateConditionVariable() {
128 return scoped_ptr<ConditionVariable>(new ConditionVariable(&lock_));
129 }
130
131 } // namespace internal
132 } // base
OLDNEW
« no previous file with comments | « base/task_scheduler/scheduler_lock_impl.h ('k') | base/task_scheduler/scheduler_lock_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698