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