15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2007, Google Inc.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// All rights reserved.
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Redistribution and use in source and binary forms, with or without
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// modification, are permitted provided that the following conditions are
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// met:
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//     * Redistributions of source code must retain the above copyright
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// notice, this list of conditions and the following disclaimer.
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//     * Redistributions in binary form must reproduce the above
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// copyright notice, this list of conditions and the following disclaimer
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// in the documentation and/or other materials provided with the
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// distribution.
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//     * Neither the name of Google Inc. nor the names of its
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// contributors may be used to endorse or promote products derived from
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// this software without specific prior written permission.
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ---
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Author: Craig Silverstein.
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// A simple mutex wrapper, supporting locks and read-write locks.
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// You should assume the locks are *not* re-entrant.
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// To use: you should define the following macros in your configure.ac:
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   ACX_PTHREAD
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   AC_RWLOCK
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The latter is defined in ../autoconf.
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This class is meant to be internal-only and should be wrapped by an
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// internal namespace.  Before you use this module, please give the
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// name of your internal namespace for this module.  Or, if you want
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// to expose it, you'll want to move it to the Google namespace.  We
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// cannot put this class in global namespace because there can be some
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// problems when we have multiple versions of Mutex in each shared object.
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// NOTE: TryLock() is broken for NO_THREADS mode, at least in NDEBUG
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//       mode.
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// CYGWIN NOTE: Cygwin support for rwlock seems to be buggy:
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//    http://www.cygwin.com/ml/cygwin/2008-12/msg00017.html
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Because of that, we might as well use windows locks for
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// cygwin.  They seem to be more reliable than the cygwin pthreads layer.
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TRICKY IMPLEMENTATION NOTE:
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This class is designed to be safe to use during
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// dynamic-initialization -- that is, by global constructors that are
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// run before main() starts.  The issue in this case is that
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// dynamic-initialization happens in an unpredictable order, and it
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// could be that someone else's dynamic initializer could call a
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// function that tries to acquire this mutex -- but that all happens
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// before this mutex's constructor has run.  (This can happen even if
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the mutex and the function that uses the mutex are in the same .cc
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// file.)  Basically, because Mutex does non-trivial work in its
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// constructor, it's not, in the naive implementation, safe to use
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// before dynamic initialization has run on it.
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The solution used here is to pair the actual mutex primitive with a
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// bool that is set to true when the mutex is dynamically initialized.
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// (Before that it's false.)  Then we modify all mutex routines to
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// look at the bool, and not try to lock/unlock until the bool makes
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// it to true (which happens after the Mutex constructor has run.)
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This works because before main() starts -- particularly, during
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// dynamic initialization -- there are no threads, so a) it's ok that
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the mutex operations are a no-op, since we don't need locking then
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// anyway; and b) we can be quite confident our bool won't change
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// state between a call to Lock() and a call to Unlock() (that would
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// require a global constructor in one translation unit to call Lock()
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// and another global constructor in another translation unit to call
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Unlock() later, which is pretty perverse).
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// That said, it's tricky, and can conceivably fail; it's safest to
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// avoid trying to acquire a mutex in a global constructor, if you
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// can.  One way it can fail is that a really smart compiler might
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// initialize the bool to true at static-initialization time (too
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// early) rather than at dynamic-initialization time.  To discourage
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// that, we set is_safe_ to true in code (not the constructor
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// colon-initializer) and set it to true via a function that always
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// evaluates to true, but that the compiler can't know always
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// evaluates to true.  This should be good enough.
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// A related issue is code that could try to access the mutex
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// after it's been destroyed in the global destructors (because
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the Mutex global destructor runs before some other global
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// destructor, that tries to acquire the mutex).  The way we
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// deal with this is by taking a constructor arg that global
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// mutexes should pass in, that causes the destructor to do no
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// work.  We still depend on the compiler not doing anything
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// weird to a Mutex's memory after it is destroyed, but for a
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static global variable, that's pretty safe.
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef GOOGLE_MUTEX_H_
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define GOOGLE_MUTEX_H_
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <config.h>
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(NO_THREADS)
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  typedef int MutexType;      // to keep a lock-count
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#elif defined(_WIN32) || defined(__CYGWIN__) || defined(__CYGWIN32__)
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# ifndef WIN32_LEAN_AND_MEAN
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#   define WIN32_LEAN_AND_MEAN  // We only need minimal includes
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# endif
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We need Windows NT or later for TryEnterCriticalSection().  If you
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // don't need that functionality, you can remove these _WIN32_WINNT
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // lines, and change TryLock() to assert(0) or something.
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# ifndef _WIN32_WINNT
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#   define _WIN32_WINNT 0x0400
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# endif
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# include <windows.h>
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  typedef CRITICAL_SECTION MutexType;
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#elif defined(HAVE_PTHREAD) && defined(HAVE_RWLOCK)
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Needed for pthread_rwlock_*.  If it causes problems, you could take it
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // out, but then you'd have to unset HAVE_RWLOCK (at least on linux -- it
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // *does* cause problems for FreeBSD, or MacOSX, but isn't needed
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // for locking there.)
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# ifdef __linux__
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#   define _XOPEN_SOURCE 500  // may be needed to get the rwlock calls
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# endif
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# include <pthread.h>
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  typedef pthread_rwlock_t MutexType;
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#elif defined(HAVE_PTHREAD)
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# include <pthread.h>
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  typedef pthread_mutex_t MutexType;
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# error Need to implement mutex.h for your architecture, or #define NO_THREADS
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <assert.h>
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/abort.h"
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define MUTEX_NAMESPACE perftools_mutex_namespace
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace MUTEX_NAMESPACE {
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class Mutex {
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This is used for the single-arg constructor
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  enum LinkerInitialized { LINKER_INITIALIZED };
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Create a Mutex that is not held by anybody.  This constructor is
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // typically used for Mutexes allocated on the heap or the stack.
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline Mutex();
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This constructor should be used for global, static Mutex objects.
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // It inhibits work being done by the destructor, which makes it
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // safer for code that tries to acqiure this mutex in their global
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // destructor.
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline Mutex(LinkerInitialized);
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Destructor
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline ~Mutex();
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline void Lock();    // Block if needed until free then acquire exclusively
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline void Unlock();  // Release a lock acquired via Lock()
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline bool TryLock(); // If free, Lock() and return true, else return false
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Note that on systems that don't support read-write locks, these may
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // be implemented as synonyms to Lock() and Unlock().  So you can use
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // these for efficiency, but don't use them anyplace where being able
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // to do shared reads is necessary to avoid deadlock.
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline void ReaderLock();   // Block until free or shared then acquire a share
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline void ReaderUnlock(); // Release a read share of this Mutex
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline void WriterLock() { Lock(); }     // Acquire an exclusive lock
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline void WriterUnlock() { Unlock(); } // Release a lock from WriterLock()
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MutexType mutex_;
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We want to make sure that the compiler sets is_safe_ to true only
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // when we tell it to, and never makes assumptions is_safe_ is
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // always true.  volatile is the most reliable way to do that.
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  volatile bool is_safe_;
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This indicates which constructor was called.
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool destroy_;
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline void SetIsSafe() { is_safe_ = true; }
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Catch the error of writing Mutex when intending MutexLock.
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Mutex(Mutex* /*ignored*/) {}
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Disallow "evil" constructors
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Mutex(const Mutex&);
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void operator=(const Mutex&);
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Now the implementation of Mutex for various systems
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(NO_THREADS)
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// When we don't have threads, we can be either reading or writing,
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// but not both.  We can have lots of readers at once (in no-threads
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// mode, that's most likely to happen in recursive function calls),
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// but only one writer.  We represent this by having mutex_ be -1 when
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// writing and a number > 0 when reading (and 0 when no lock is held).
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// In debug mode, we assert these invariants, while in non-debug mode
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// we do nothing, for efficiency.  That's why everything is in an
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// assert.
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Mutex::Mutex() : mutex_(0) { }
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Mutex::Mutex(Mutex::LinkerInitialized) : mutex_(0) { }
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Mutex::~Mutex()            { assert(mutex_ == 0); }
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Mutex::Lock()         { assert(--mutex_ == -1); }
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Mutex::Unlock()       { assert(mutex_++ == -1); }
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool Mutex::TryLock()      { if (mutex_) return false; Lock(); return true; }
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Mutex::ReaderLock()   { assert(++mutex_ > 0); }
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Mutex::ReaderUnlock() { assert(mutex_-- > 0); }
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#elif defined(_WIN32) || defined(__CYGWIN__) || defined(__CYGWIN32__)
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Mutex::Mutex() : destroy_(true) {
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  InitializeCriticalSection(&mutex_);
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SetIsSafe();
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Mutex::Mutex(LinkerInitialized) : destroy_(false) {
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  InitializeCriticalSection(&mutex_);
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SetIsSafe();
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Mutex::~Mutex()            { if (destroy_) DeleteCriticalSection(&mutex_); }
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Mutex::Lock()         { if (is_safe_) EnterCriticalSection(&mutex_); }
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Mutex::Unlock()       { if (is_safe_) LeaveCriticalSection(&mutex_); }
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool Mutex::TryLock()      { return is_safe_ ?
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 TryEnterCriticalSection(&mutex_) != 0 : true; }
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Mutex::ReaderLock()   { Lock(); }      // we don't have read-write locks
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Mutex::ReaderUnlock() { Unlock(); }
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#elif defined(HAVE_PTHREAD) && defined(HAVE_RWLOCK)
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define SAFE_PTHREAD(fncall)  do {   /* run fncall if is_safe_ is true */  \
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (is_safe_ && fncall(&mutex_) != 0) tcmalloc::Abort();                 \
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} while (0)
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Mutex::Mutex() : destroy_(true) {
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SetIsSafe();
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (is_safe_ && pthread_rwlock_init(&mutex_, NULL) != 0) tcmalloc::Abort();
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Mutex::Mutex(Mutex::LinkerInitialized) : destroy_(false) {
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SetIsSafe();
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (is_safe_ && pthread_rwlock_init(&mutex_, NULL) != 0) tcmalloc::Abort();
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Mutex::~Mutex()       { if (destroy_) SAFE_PTHREAD(pthread_rwlock_destroy); }
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Mutex::Lock()         { SAFE_PTHREAD(pthread_rwlock_wrlock); }
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Mutex::Unlock()       { SAFE_PTHREAD(pthread_rwlock_unlock); }
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool Mutex::TryLock()      { return is_safe_ ?
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               pthread_rwlock_trywrlock(&mutex_) == 0 : true; }
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Mutex::ReaderLock()   { SAFE_PTHREAD(pthread_rwlock_rdlock); }
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Mutex::ReaderUnlock() { SAFE_PTHREAD(pthread_rwlock_unlock); }
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#undef SAFE_PTHREAD
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#elif defined(HAVE_PTHREAD)
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define SAFE_PTHREAD(fncall)  do {   /* run fncall if is_safe_ is true */  \
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (is_safe_ && fncall(&mutex_) != 0) tcmalloc::Abort();                 \
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} while (0)
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Mutex::Mutex() : destroy_(true) {
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SetIsSafe();
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (is_safe_ && pthread_mutex_init(&mutex_, NULL) != 0) tcmalloc::Abort();
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Mutex::Mutex(Mutex::LinkerInitialized) : destroy_(false) {
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SetIsSafe();
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (is_safe_ && pthread_mutex_init(&mutex_, NULL) != 0) tcmalloc::Abort();
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Mutex::~Mutex()       { if (destroy_) SAFE_PTHREAD(pthread_mutex_destroy); }
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Mutex::Lock()         { SAFE_PTHREAD(pthread_mutex_lock); }
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Mutex::Unlock()       { SAFE_PTHREAD(pthread_mutex_unlock); }
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool Mutex::TryLock()      { return is_safe_ ?
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 pthread_mutex_trylock(&mutex_) == 0 : true; }
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Mutex::ReaderLock()   { Lock(); }
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Mutex::ReaderUnlock() { Unlock(); }
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#undef SAFE_PTHREAD
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// --------------------------------------------------------------------------
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Some helper classes
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// MutexLock(mu) acquires mu when constructed and releases it when destroyed.
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class MutexLock {
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  explicit MutexLock(Mutex *mu) : mu_(mu) { mu_->Lock(); }
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ~MutexLock() { mu_->Unlock(); }
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Mutex * const mu_;
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Disallow "evil" constructors
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MutexLock(const MutexLock&);
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void operator=(const MutexLock&);
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ReaderMutexLock and WriterMutexLock do the same, for rwlocks
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ReaderMutexLock {
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  explicit ReaderMutexLock(Mutex *mu) : mu_(mu) { mu_->ReaderLock(); }
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ~ReaderMutexLock() { mu_->ReaderUnlock(); }
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Mutex * const mu_;
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Disallow "evil" constructors
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ReaderMutexLock(const ReaderMutexLock&);
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void operator=(const ReaderMutexLock&);
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class WriterMutexLock {
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  explicit WriterMutexLock(Mutex *mu) : mu_(mu) { mu_->WriterLock(); }
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ~WriterMutexLock() { mu_->WriterUnlock(); }
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Mutex * const mu_;
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Disallow "evil" constructors
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WriterMutexLock(const WriterMutexLock&);
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void operator=(const WriterMutexLock&);
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Catch bug where variable name is omitted, e.g. MutexLock (&mu);
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define MutexLock(x) COMPILE_ASSERT(0, mutex_lock_decl_missing_var_name)
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define ReaderMutexLock(x) COMPILE_ASSERT(0, rmutex_lock_decl_missing_var_name)
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define WriterMutexLock(x) COMPILE_ASSERT(0, wmutex_lock_decl_missing_var_name)
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace MUTEX_NAMESPACE
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using namespace MUTEX_NAMESPACE;
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#undef MUTEX_NAMESPACE
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif  /* #define GOOGLE_SIMPLE_MUTEX_H_ */
332