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