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