Initial windows support. Now we don't have the stacktrace and several unittests.
[platform/upstream/glog.git] / src / base / mutex.h
1 /* Copyright (c) 2007, Google Inc.
2  * All rights reserved.
3  * 
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are
6  * met:
7  * 
8  *     * Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  *     * Redistributions in binary form must reproduce the above
11  * copyright notice, this list of conditions and the following disclaimer
12  * in the documentation and/or other materials provided with the
13  * distribution.
14  *     * Neither the name of Google Inc. nor the names of its
15  * contributors may be used to endorse or promote products derived from
16  * this software without specific prior written permission.
17  * 
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  *
30  * ---
31  * Author: Craig Silverstein.
32  *
33  * A simple mutex wrapper, supporting locks and read-write locks.
34  * You should assume the locks are *not* re-entrant.
35  *
36  * To use: you should define the following macros in your configure.ac:
37  *   ACX_PTHREAD
38  *   AC_RWLOCK
39  * The latter is defined in ../autoconf.
40  *
41  * This class is meant to be internal-only, so it's defined in the
42  * global namespace.  If you want to expose it, you'll want to move
43  * it to the Google namespace.
44  *
45  * NOTE: by default, we have #ifdef'ed out the TryLock() method.
46  *       This is for two reasons:
47  * 1) TryLock() under Windows is a bit annoying (it requires a
48  *    #define to be defined very early).
49  * 2) TryLock() is broken for NO_THREADS mode, at least in NDEBUG
50  *    mode.
51  * If you need TryLock(), and either these two caveats are not a
52  * problem for you, or you're willing to work around them, then
53  * feel free to #define GMUTEX_TRYLOCK, or to remove the #ifdefs
54  * in the code below.
55  */
56
57 // TODO(hamaji): Probably we must provide way to ensure static mutexes are
58 //               initialized before they are used.
59 //               (Google3's NO_CONSTRUCTOR_NEEDED_FOR_STATIC_MUTEX)
60
61 #ifndef GOOGLE_MUTEX_H__
62 #define GOOGLE_MUTEX_H__
63
64 #include "config.h"           // to figure out pthreads support
65 #include "utilities.h"        // to get OS_* macro
66
67 #if defined(NO_THREADS)
68   typedef int MutexType;      // to keep a lock-count
69 #elif defined(HAVE_PTHREAD) && defined(HAVE_RWLOCK)
70   // Needed for pthread_rwlock_*.  If it causes problems, you could take it
71   // out, but then you'd have to unset HAVE_RWLOCK (at least on linux -- it
72   // *does* cause problems for FreeBSD, or MacOSX, but isn't needed
73   // for locking there.)
74 # ifdef __linux__
75 #   define _XOPEN_SOURCE 500  // may be needed to get the rwlock calls
76 # endif
77 # include <pthread.h>
78   typedef pthread_rwlock_t MutexType;
79 #elif defined(HAVE_PTHREAD)
80 # include <pthread.h>
81   typedef pthread_mutex_t MutexType;
82 #elif defined(OS_WINDOWS)
83 # define WIN32_LEAN_AND_MEAN  // We only need minimal includes
84 # ifdef GMUTEX_TRYLOCK
85   // We need Windows NT or later for TryEnterCriticalSection().  If you
86   // don't need that functionality, you can remove these _WIN32_WINNT
87   // lines, and change TryLock() to assert(0) or something.
88 #   ifndef _WIN32_WINNT
89 #     define _WIN32_WINNT 0x0400
90 #   endif
91 # endif
92 // To avoid macro definition of ERROR.
93 # define NOGDI
94 # include <windows.h>
95   typedef CRITICAL_SECTION MutexType;
96 #else
97 # error Need to implement mutex.h for your architecture, or #define NO_THREADS
98 #endif
99
100 class Mutex {
101  public:
102   // Create a Mutex that is not held by anybody.  This constructor is
103   // typically used for Mutexes allocated on the heap or the stack.
104   // See below for a recommendation for constructing global Mutex
105   // objects.
106   inline Mutex();
107
108   // Destructor
109   inline ~Mutex();
110
111   inline void Lock();    // Block if needed until free then acquire exclusively
112   inline void Unlock();  // Release a lock acquired via Lock()
113 #ifdef GMUTEX_TRYLOCK
114   inline bool TryLock(); // If free, Lock() and return true, else return false
115 #endif
116   // Note that on systems that don't support read-write locks, these may
117   // be implemented as synonyms to Lock() and Unlock().  So you can use
118   // these for efficiency, but don't use them anyplace where being able
119   // to do shared reads is necessary to avoid deadlock.
120   inline void ReaderLock();   // Block until free or shared then acquire a share
121   inline void ReaderUnlock(); // Release a read share of this Mutex
122   inline void WriterLock() { Lock(); }     // Acquire an exclusive lock
123   inline void WriterUnlock() { Unlock(); } // Release a lock from WriterLock()
124
125   // TODO(hamaji): Do nothing, implement correctly.
126   inline void AssertHeld() {}
127
128  private:
129   MutexType mutex_;
130
131   // Catch the error of writing Mutex when intending MutexLock.
132   Mutex(Mutex *ignored) {}
133   // Disallow "evil" constructors
134   Mutex(const Mutex&);
135   void operator=(const Mutex&);
136 };
137
138 // Now the implementation of Mutex for various systems
139 #if defined(NO_THREADS)
140
141 // When we don't have threads, we can be either reading or writing,
142 // but not both.  We can have lots of readers at once (in no-threads
143 // mode, that's most likely to happen in recursive function calls),
144 // but only one writer.  We represent this by having mutex_ be -1 when
145 // writing and a number > 0 when reading (and 0 when no lock is held).
146 //
147 // In debug mode, we assert these invariants, while in non-debug mode
148 // we do nothing, for efficiency.  That's why everything is in an
149 // assert.
150 #include <assert.h>
151
152 Mutex::Mutex() : mutex_(0) { }
153 Mutex::~Mutex()            { assert(mutex_ == 0); }
154 void Mutex::Lock()         { assert(--mutex_ == -1); }
155 void Mutex::Unlock()       { assert(mutex_++ == -1); }
156 #ifdef GMUTEX_TRYLOCK
157 bool Mutex::TryLock()      { if (mutex_) return false; Lock(); return true; }
158 #endif
159 void Mutex::ReaderLock()   { assert(++mutex_ > 0); }
160 void Mutex::ReaderUnlock() { assert(mutex_-- > 0); }
161
162 #elif defined(HAVE_PTHREAD) && defined(HAVE_RWLOCK)
163
164 #include <stdlib.h>      // for abort()
165 #define SAFE_PTHREAD(fncall)  do { if ((fncall) != 0) abort(); } while (0)
166
167 Mutex::Mutex()             { SAFE_PTHREAD(pthread_rwlock_init(&mutex_, NULL)); }
168 Mutex::~Mutex()            { SAFE_PTHREAD(pthread_rwlock_destroy(&mutex_)); }
169 void Mutex::Lock()         { SAFE_PTHREAD(pthread_rwlock_wrlock(&mutex_)); }
170 void Mutex::Unlock()       { SAFE_PTHREAD(pthread_rwlock_unlock(&mutex_)); }
171 #ifdef GMUTEX_TRYLOCK
172 bool Mutex::TryLock()      { return pthread_rwlock_trywrlock(&mutex_) == 0; }
173 #endif
174 void Mutex::ReaderLock()   { SAFE_PTHREAD(pthread_rwlock_rdlock(&mutex_)); }
175 void Mutex::ReaderUnlock() { SAFE_PTHREAD(pthread_rwlock_unlock(&mutex_)); }
176 #undef SAFE_PTHREAD
177
178 #elif defined(HAVE_PTHREAD)
179
180 #include <stdlib.h>      // for abort()
181 #define SAFE_PTHREAD(fncall)  do { if ((fncall) != 0) abort(); } while (0)
182
183 Mutex::Mutex()             { SAFE_PTHREAD(pthread_mutex_init(&mutex_, NULL)); }
184 Mutex::~Mutex()            { SAFE_PTHREAD(pthread_mutex_destroy(&mutex_)); }
185 void Mutex::Lock()         { SAFE_PTHREAD(pthread_mutex_lock(&mutex_)); }
186 void Mutex::Unlock()       { SAFE_PTHREAD(pthread_mutex_unlock(&mutex_)); }
187 #ifdef GMUTEX_TRYLOCK
188 bool Mutex::TryLock()      { return pthread_mutex_trylock(&mutex_) == 0; }
189 #endif
190 void Mutex::ReaderLock()   { Lock(); }      // we don't have read-write locks
191 void Mutex::ReaderUnlock() { Unlock(); }
192 #undef SAFE_PTHREAD
193
194 #elif defined(WIN32)
195
196 Mutex::Mutex()             { InitializeCriticalSection(&mutex_); }
197 Mutex::~Mutex()            { DeleteCriticalSection(&mutex_); }
198 void Mutex::Lock()         { EnterCriticalSection(&mutex_); }
199 void Mutex::Unlock()       { LeaveCriticalSection(&mutex_); }
200 #ifdef GMUTEX_TRYLOCK
201 bool Mutex::TryLock()      { return TryEnterCriticalSection(&mutex_) != 0; }
202 #endif
203 void Mutex::ReaderLock()   { Lock(); }      // we don't have read-write locks
204 void Mutex::ReaderUnlock() { Unlock(); }
205
206 #endif
207
208
209 // --------------------------------------------------------------------------
210 // Some helper classes
211
212 // MutexLock(mu) acquires mu when constructed and releases it when destroyed.
213 class MutexLock {
214  public:
215   explicit MutexLock(Mutex *mu) : mu_(mu) { mu_->Lock(); }
216   ~MutexLock() { mu_->Unlock(); }
217  private:
218   Mutex * const mu_;
219   // Disallow "evil" constructors
220   MutexLock(const MutexLock&);
221   void operator=(const MutexLock&);
222 };
223
224 // ReaderMutexLock and WriterMutexLock do the same, for rwlocks
225 class ReaderMutexLock {
226  public:
227   explicit ReaderMutexLock(Mutex *mu) : mu_(mu) { mu_->ReaderLock(); }
228   ~ReaderMutexLock() { mu_->ReaderUnlock(); }
229  private:
230   Mutex * const mu_;
231   // Disallow "evil" constructors
232   ReaderMutexLock(const ReaderMutexLock&);
233   void operator=(const ReaderMutexLock&);
234 };
235
236 class WriterMutexLock {
237  public:
238   explicit WriterMutexLock(Mutex *mu) : mu_(mu) { mu_->WriterLock(); }
239   ~WriterMutexLock() { mu_->WriterUnlock(); }
240  private:
241   Mutex * const mu_;
242   // Disallow "evil" constructors
243   WriterMutexLock(const WriterMutexLock&);
244   void operator=(const WriterMutexLock&);
245 };
246
247 // Catch bug where variable name is omitted, e.g. MutexLock (&mu);
248 #define MutexLock(x) COMPILE_ASSERT(0, mutex_lock_decl_missing_var_name)
249 #define ReaderMutexLock(x) COMPILE_ASSERT(0, rmutex_lock_decl_missing_var_name)
250 #define WriterMutexLock(x) COMPILE_ASSERT(0, wmutex_lock_decl_missing_var_name)
251
252 #endif  /* #define GOOGLE_MUTEX_H__ */