security/sandbox/chromium/base/synchronization/lock.h

Wed, 31 Dec 2014 06:55:50 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:55:50 +0100
changeset 2
7e26c7da4463
permissions
-rw-r--r--

Added tag UPSTREAM_283F7C6 for changeset ca08bd8f51b2

michael@0 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
michael@0 2 // Use of this source code is governed by a BSD-style license that can be
michael@0 3 // found in the LICENSE file.
michael@0 4
michael@0 5 #ifndef BASE_SYNCHRONIZATION_LOCK_H_
michael@0 6 #define BASE_SYNCHRONIZATION_LOCK_H_
michael@0 7
michael@0 8 #include "base/base_export.h"
michael@0 9 #include "base/synchronization/lock_impl.h"
michael@0 10 #include "base/threading/platform_thread.h"
michael@0 11
michael@0 12 namespace base {
michael@0 13
michael@0 14 // A convenient wrapper for an OS specific critical section. The only real
michael@0 15 // intelligence in this class is in debug mode for the support for the
michael@0 16 // AssertAcquired() method.
michael@0 17 class BASE_EXPORT Lock {
michael@0 18 public:
michael@0 19 #if defined(NDEBUG) // Optimized wrapper implementation
michael@0 20 Lock() : lock_() {}
michael@0 21 ~Lock() {}
michael@0 22 void Acquire() { lock_.Lock(); }
michael@0 23 void Release() { lock_.Unlock(); }
michael@0 24
michael@0 25 // If the lock is not held, take it and return true. If the lock is already
michael@0 26 // held by another thread, immediately return false. This must not be called
michael@0 27 // by a thread already holding the lock (what happens is undefined and an
michael@0 28 // assertion may fail).
michael@0 29 bool Try() { return lock_.Try(); }
michael@0 30
michael@0 31 // Null implementation if not debug.
michael@0 32 void AssertAcquired() const {}
michael@0 33 #else
michael@0 34 Lock();
michael@0 35 ~Lock();
michael@0 36
michael@0 37 // NOTE: Although windows critical sections support recursive locks, we do not
michael@0 38 // allow this, and we will commonly fire a DCHECK() if a thread attempts to
michael@0 39 // acquire the lock a second time (while already holding it).
michael@0 40 void Acquire() {
michael@0 41 lock_.Lock();
michael@0 42 CheckUnheldAndMark();
michael@0 43 }
michael@0 44 void Release() {
michael@0 45 CheckHeldAndUnmark();
michael@0 46 lock_.Unlock();
michael@0 47 }
michael@0 48
michael@0 49 bool Try() {
michael@0 50 bool rv = lock_.Try();
michael@0 51 if (rv) {
michael@0 52 CheckUnheldAndMark();
michael@0 53 }
michael@0 54 return rv;
michael@0 55 }
michael@0 56
michael@0 57 void AssertAcquired() const;
michael@0 58 #endif // NDEBUG
michael@0 59
michael@0 60 #if defined(OS_POSIX)
michael@0 61 // The posix implementation of ConditionVariable needs to be able
michael@0 62 // to see our lock and tweak our debugging counters, as it releases
michael@0 63 // and acquires locks inside of pthread_cond_{timed,}wait.
michael@0 64 friend class ConditionVariable;
michael@0 65 #elif defined(OS_WIN)
michael@0 66 // The Windows Vista implementation of ConditionVariable needs the
michael@0 67 // native handle of the critical section.
michael@0 68 friend class WinVistaCondVar;
michael@0 69 #endif
michael@0 70
michael@0 71 private:
michael@0 72 #if !defined(NDEBUG)
michael@0 73 // Members and routines taking care of locks assertions.
michael@0 74 // Note that this checks for recursive locks and allows them
michael@0 75 // if the variable is set. This is allowed by the underlying implementation
michael@0 76 // on windows but not on Posix, so we're doing unneeded checks on Posix.
michael@0 77 // It's worth it to share the code.
michael@0 78 void CheckHeldAndUnmark();
michael@0 79 void CheckUnheldAndMark();
michael@0 80
michael@0 81 // All private data is implicitly protected by lock_.
michael@0 82 // Be VERY careful to only access members under that lock.
michael@0 83
michael@0 84 // Determines validity of owning_thread_id_. Needed as we don't have
michael@0 85 // a null owning_thread_id_ value.
michael@0 86 bool owned_by_thread_;
michael@0 87 base::PlatformThreadId owning_thread_id_;
michael@0 88 #endif // NDEBUG
michael@0 89
michael@0 90 // Platform specific underlying lock implementation.
michael@0 91 internal::LockImpl lock_;
michael@0 92
michael@0 93 DISALLOW_COPY_AND_ASSIGN(Lock);
michael@0 94 };
michael@0 95
michael@0 96 // A helper class that acquires the given Lock while the AutoLock is in scope.
michael@0 97 class AutoLock {
michael@0 98 public:
michael@0 99 struct AlreadyAcquired {};
michael@0 100
michael@0 101 explicit AutoLock(Lock& lock) : lock_(lock) {
michael@0 102 lock_.Acquire();
michael@0 103 }
michael@0 104
michael@0 105 AutoLock(Lock& lock, const AlreadyAcquired&) : lock_(lock) {
michael@0 106 lock_.AssertAcquired();
michael@0 107 }
michael@0 108
michael@0 109 ~AutoLock() {
michael@0 110 lock_.AssertAcquired();
michael@0 111 lock_.Release();
michael@0 112 }
michael@0 113
michael@0 114 private:
michael@0 115 Lock& lock_;
michael@0 116 DISALLOW_COPY_AND_ASSIGN(AutoLock);
michael@0 117 };
michael@0 118
michael@0 119 // AutoUnlock is a helper that will Release() the |lock| argument in the
michael@0 120 // constructor, and re-Acquire() it in the destructor.
michael@0 121 class AutoUnlock {
michael@0 122 public:
michael@0 123 explicit AutoUnlock(Lock& lock) : lock_(lock) {
michael@0 124 // We require our caller to have the lock.
michael@0 125 lock_.AssertAcquired();
michael@0 126 lock_.Release();
michael@0 127 }
michael@0 128
michael@0 129 ~AutoUnlock() {
michael@0 130 lock_.Acquire();
michael@0 131 }
michael@0 132
michael@0 133 private:
michael@0 134 Lock& lock_;
michael@0 135 DISALLOW_COPY_AND_ASSIGN(AutoUnlock);
michael@0 136 };
michael@0 137
michael@0 138 } // namespace base
michael@0 139
michael@0 140 #endif // BASE_SYNCHRONIZATION_LOCK_H_

mercurial