mutex.h revision 25fd14b87cced64a179dee885573113be5e11944
18daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes/* 28daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes * Copyright (C) 2011 The Android Open Source Project 38daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes * 48daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes * Licensed under the Apache License, Version 2.0 (the "License"); 58daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes * you may not use this file except in compliance with the License. 68daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes * You may obtain a copy of the License at 78daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes * 88daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes * http://www.apache.org/licenses/LICENSE-2.0 98daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes * 108daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes * Unless required by applicable law or agreed to in writing, software 118daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes * distributed under the License is distributed on an "AS IS" BASIS, 128daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 138daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes * See the License for the specific language governing permissions and 148daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes * limitations under the License. 158daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes */ 168daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes 178daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes#ifndef ART_SRC_MUTEX_H_ 188daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes#define ART_SRC_MUTEX_H_ 198daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes 208daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes#include <pthread.h> 21cd74c4b3a6893c876c6e03fd99a1264249653d80Brian Carlstrom#include <stdint.h> 22ffb465f23d9549dd591e6aa62e9250523cb00233Elliott Hughes 23ffb465f23d9549dd591e6aa62e9250523cb00233Elliott Hughes#include <iosfwd> 248daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes#include <string> 258daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes 2600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers#include "globals.h" 278daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes#include "logging.h" 288daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes#include "macros.h" 298daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes 3066aee5cd571cf4739d2735769304202ea5051fb8Ian Rogers// Currently Darwin doesn't support locks with timeouts. 3166aee5cd571cf4739d2735769304202ea5051fb8Ian Rogers#if !defined(__APPLE__) 3266aee5cd571cf4739d2735769304202ea5051fb8Ian Rogers#define HAVE_TIMED_RWLOCK 1 3366aee5cd571cf4739d2735769304202ea5051fb8Ian Rogers#else 3466aee5cd571cf4739d2735769304202ea5051fb8Ian Rogers#define HAVE_TIMED_RWLOCK 0 3566aee5cd571cf4739d2735769304202ea5051fb8Ian Rogers#endif 3666aee5cd571cf4739d2735769304202ea5051fb8Ian Rogers 378daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughesnamespace art { 388daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes 3925fd14b87cced64a179dee885573113be5e11944Ian Rogersconst bool kDebugLocking = kIsDebugBuild; 4025fd14b87cced64a179dee885573113be5e11944Ian Rogers 4100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogersclass LOCKABLE Mutex; 4200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogersclass LOCKABLE ReaderWriterMutex; 4300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers 4400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// MutexLevel is used to impose a lock hierarchy [1] where acquisition of a Mutex at a higher or 4500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// equal level to a lock a thread holds is invalid. The lock hierarchy achieves a cycle free 4600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// partial ordering and thereby cause deadlock situations to fail checks. 4700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// 4800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// [1] http://www.drdobbs.com/parallel/use-lock-hierarchies-to-avoid-deadlock/204801163 4900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogersenum MutexLevel { 5000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers kLoggingLock = 0, 5100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers kUnexpectedSignalLock = 1, 52ffb465f23d9549dd591e6aa62e9250523cb00233Elliott Hughes kThreadSuspendCountLock = 2, 5300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers kAbortLock = 3, 5400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers kDefaultMutexLevel = 4, 5515bf2d34efa2218e287b584fb3653d268b9edc8dIan Rogers kJdwpSerialLock = 5, 5615bf2d34efa2218e287b584fb3653d268b9edc8dIan Rogers kAllocSpaceLock = 6, 5715bf2d34efa2218e287b584fb3653d268b9edc8dIan Rogers kLoadLibraryLock = 7, 5815bf2d34efa2218e287b584fb3653d268b9edc8dIan Rogers kClassLinkerClassesLock = 8, 5915bf2d34efa2218e287b584fb3653d268b9edc8dIan Rogers kThreadListLock = 9, 6015bf2d34efa2218e287b584fb3653d268b9edc8dIan Rogers kHeapBitmapLock = 10, 6115bf2d34efa2218e287b584fb3653d268b9edc8dIan Rogers kMonitorLock = 11, 6215bf2d34efa2218e287b584fb3653d268b9edc8dIan Rogers kMutatorLock = 12, 6315bf2d34efa2218e287b584fb3653d268b9edc8dIan Rogers kZygoteCreationLock = 13, 6400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers kMaxMutexLevel = kMutatorLock, 65ffb465f23d9549dd591e6aa62e9250523cb00233Elliott Hughes}; 6600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogersstd::ostream& operator<<(std::ostream& os, const MutexLevel& rhs); 67ffb465f23d9549dd591e6aa62e9250523cb00233Elliott Hughes 6800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// Global mutexes corresponding to the levels above. 69b726dcb581bf72da46527378ccb6889020f0e6e9Ian Rogersclass Locks { 708daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes public: 7100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers static void Init(); 728daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes 7300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // The mutator_lock_ is used to allow mutators to execute in a shared (reader) mode or to block 7400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // mutators by having an exclusive (writer) owner. In normal execution each mutator thread holds 7500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // a share on the mutator_lock_. The garbage collector may also execute with shared access but 7600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // at times requires exclusive access to the heap (not to be confused with the heap meta-data 7700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // guarded by the heap_lock_ below). When the garbage collector requires exclusive access it asks 7800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // the mutators to suspend themselves which also involves usage of the thread_suspend_count_lock_ 7900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // to cover weaknesses in using ReaderWriterMutexes with ConditionVariables. We use a condition 8000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // variable to wait upon in the suspension logic as releasing and then re-acquiring a share on 8100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // the mutator lock doesn't necessarily allow the exclusive user (e.g the garbage collector) 8200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // chance to acquire the lock. 8300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // 8400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // Thread suspension: 8500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // Shared users | Exclusive user 8600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // (holding mutator lock and in kRunnable state) | .. running .. 8700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // .. running .. | Request thread suspension by: 8800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // .. running .. | - acquiring thread_suspend_count_lock_ 8900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // .. running .. | - incrementing Thread::suspend_count_ on 9000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // .. running .. | all mutator threads 9100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // .. running .. | - releasing thread_suspend_count_lock_ 9200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // .. running .. | Block trying to acquire exclusive mutator lock 9300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // Poll Thread::suspend_count_ and enter full | .. blocked .. 9400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // suspend code. | .. blocked .. 9500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // Change state to kSuspended | .. blocked .. 9600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // x: Release share on mutator_lock_ | Carry out exclusive access 9700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // Acquire thread_suspend_count_lock_ | .. exclusive .. 9800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // while Thread::suspend_count_ > 0 | .. exclusive .. 9900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // - wait on Thread::resume_cond_ | .. exclusive .. 10000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // (releases thread_suspend_count_lock_) | .. exclusive .. 10100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // .. waiting .. | Release mutator_lock_ 10200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // .. waiting .. | Request thread resumption by: 10300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // .. waiting .. | - acquiring thread_suspend_count_lock_ 10400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // .. waiting .. | - decrementing Thread::suspend_count_ on 10500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // .. waiting .. | all mutator threads 10600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // .. waiting .. | - notifying on Thread::resume_cond_ 10700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // - re-acquire thread_suspend_count_lock_ | - releasing thread_suspend_count_lock_ 10800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // Release thread_suspend_count_lock_ | .. running .. 10900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // Acquire share on mutator_lock_ | .. running .. 11000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // - This could block but the thread still | .. running .. 11100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // has a state of kSuspended and so this | .. running .. 11200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // isn't an issue. | .. running .. 11300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // Acquire thread_suspend_count_lock_ | .. running .. 11400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // - we poll here as we're transitioning into | .. running .. 11500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // kRunnable and an individual thread suspend | .. running .. 11600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // request (e.g for debugging) won't try | .. running .. 11700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // to acquire the mutator lock (which would | .. running .. 11800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // block as we hold the mutator lock). This | .. running .. 11900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // poll ensures that if the suspender thought | .. running .. 12000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // we were suspended by incrementing our | .. running .. 12100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // Thread::suspend_count_ and then reading | .. running .. 12200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // our state we go back to waiting on | .. running .. 12300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // Thread::resume_cond_. | .. running .. 12400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // can_go_runnable = Thread::suspend_count_ == 0 | .. running .. 12500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // Release thread_suspend_count_lock_ | .. running .. 12600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // if can_go_runnable | .. running .. 12700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // Change state to kRunnable | .. running .. 12800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // else | .. running .. 12900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // Goto x | .. running .. 13000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // .. running .. | .. running .. 13100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers static ReaderWriterMutex* mutator_lock_; 1328daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes 13300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // Allow reader-writer mutual exclusion on the mark and live bitmaps of the heap. 13400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers static ReaderWriterMutex* heap_bitmap_lock_ ACQUIRED_AFTER(mutator_lock_); 1358daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes 13600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // The thread_list_lock_ guards ThreadList::list_. It is also commonly held to stop threads 13700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // attaching and detaching. 13800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers static Mutex* thread_list_lock_ ACQUIRED_AFTER(heap_bitmap_lock_); 1398daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes 14000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // Guards lists of classes within the class linker. 14100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers static Mutex* classlinker_classes_lock_ ACQUIRED_AFTER(thread_list_lock_); 1428daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes 14300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // When declaring any Mutex add DEFAULT_MUTEX_ACQUIRED_AFTER to use annotalysis to check the code 14400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // doesn't try to hold a higher level Mutex. 14500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers #define DEFAULT_MUTEX_ACQUIRED_AFTER ACQUIRED_AFTER(classlinker_classes_lock_) 146accd83d1523545ac69bafd38e72a7d5cff8e2facElliott Hughes 14700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // Have an exclusive aborting thread. 14800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers static Mutex* abort_lock_ ACQUIRED_AFTER(classlinker_classes_lock_); 149cd74c4b3a6893c876c6e03fd99a1264249653d80Brian Carlstrom 15000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // Allow mutual exclusion when manipulating Thread::suspend_count_. 15100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // TODO: Does the trade-off of a per-thread lock make sense? 15200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers static Mutex* thread_suspend_count_lock_ ACQUIRED_AFTER(abort_lock_); 15300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers 15400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // One unexpected signal at a time lock. 15500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers static Mutex* unexpected_signal_lock_ ACQUIRED_AFTER(thread_suspend_count_lock_); 15600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers 15700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // Have an exclusive logging thread. 15800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers static Mutex* logging_lock_ ACQUIRED_AFTER(unexpected_signal_lock_); 15900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers}; 16000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers 16100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// Base class for all Mutex implementations 16200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogersclass BaseMutex { 16300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers public: 16400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers const std::string& GetName() const { 16500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers return name_; 16600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers } 16700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers 16800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers virtual bool IsMutex() const { return false; } 16900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers virtual bool IsReaderWriterMutex() const { return false; } 17000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers 17100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers protected: 17200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers friend class ConditionVariable; 17300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers 17400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers BaseMutex(const char* name, MutexLevel level); 17500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers virtual ~BaseMutex() {} 17600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers void RegisterAsLockedWithCurrentThread(); 17700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers void RegisterAsUnlockedWithCurrentThread(); 17800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers void CheckSafeToWait(); 17900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers 18000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers const MutexLevel level_; // Support for lock hierarchy. 1810a1038b0a30a52dff1a449a989825e808a83df80Elliott Hughes const std::string name_; 18200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers}; 18300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers 18400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// A Mutex is used to achieve mutual exclusion between threads. A Mutex can be used to gain 18500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// exclusive access to what it guards. A Mutex can be in one of two states: 18600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// - Free - not owned by any thread, 18700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// - Exclusive - owned by a single thread. 18800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// 18900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// The effect of locking and unlocking operations on the state is: 19000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// State | ExclusiveLock | ExclusiveUnlock 19100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// ------------------------------------------- 19200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// Free | Exclusive | error 19300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// Exclusive | Block* | Free 19400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// * Mutex is not reentrant and so an attempt to ExclusiveLock on the same thread will result in 19500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// an error. Being non-reentrant simplifies Waiting on ConditionVariables. 19600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogersclass LOCKABLE Mutex : public BaseMutex { 19700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers public: 19800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers explicit Mutex(const char* name, MutexLevel level = kDefaultMutexLevel, bool recursive = false); 19900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers ~Mutex(); 20000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers 20100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers virtual bool IsMutex() const { return true; } 20200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers 20300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // Block until mutex is free then acquire exclusive access. 20400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers void ExclusiveLock() EXCLUSIVE_LOCK_FUNCTION(); 20500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers void Lock() EXCLUSIVE_LOCK_FUNCTION() { ExclusiveLock(); } 20600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers 20700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // Returns true if acquires exclusive access, false otherwise. 20800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers bool ExclusiveTryLock() EXCLUSIVE_TRYLOCK_FUNCTION(true); 20900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers bool TryLock() EXCLUSIVE_TRYLOCK_FUNCTION(true) { return ExclusiveTryLock(); } 21000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers 21100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // Release exclusive access. 21200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers void ExclusiveUnlock() UNLOCK_FUNCTION(); 21300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers void Unlock() UNLOCK_FUNCTION() { ExclusiveUnlock(); } 21400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers 21500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // Is the current thread the exclusive holder of the Mutex. 21600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers bool IsExclusiveHeld() const; 2178daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes 21800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // Assert that the Mutex is exclusively held by the current thread. 21900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers void AssertExclusiveHeld() { 22025fd14b87cced64a179dee885573113be5e11944Ian Rogers if (kDebugLocking) { 22100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers CHECK(IsExclusiveHeld()); 22200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers } 22300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers } 22400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers void AssertHeld() { AssertExclusiveHeld(); } 22500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers 22600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // Assert that the Mutex is not held by the current thread. 22700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers void AssertNotHeldExclusive() { 22825fd14b87cced64a179dee885573113be5e11944Ian Rogers if (kDebugLocking) { 22900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers CHECK(!IsExclusiveHeld()); 23000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers } 23100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers } 23200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers void AssertNotHeld() { AssertNotHeldExclusive(); } 23300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers 23400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // Id associated with exclusive owner. 23500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers uint64_t GetExclusiveOwnerTid() const; 23600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers 23700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // Returns how many times this Mutex has been locked, it is better to use AssertHeld/NotHeld. 23800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers unsigned int GetDepth() const { 23900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers return recursion_count_; 24000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers } 24100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers 24200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers private: 24300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers pthread_mutex_t mutex_; 24400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers const bool recursive_; // Can the lock be recursively held? 24500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers unsigned int recursion_count_; 246f1498437b0d6beb9f4f91980b98cbeb0b5c773ceElliott Hughes friend class ConditionVariable; 2473efb8416c9809a1da3300509fd9d2bc54e22e4c2Elliott Hughes friend class MutexTester; 2488daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes DISALLOW_COPY_AND_ASSIGN(Mutex); 2498daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes}; 2508daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes 25100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// A ReaderWriterMutex is used to achieve mutual exclusion between threads, similar to a Mutex. 25200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// Unlike a Mutex a ReaderWriterMutex can be used to gain exclusive (writer) or shared (reader) 25300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// access to what it guards. A flaw in relation to a Mutex is that it cannot be used with a 25400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// condition variable. A ReaderWriterMutex can be in one of three states: 25500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// - Free - not owned by any thread, 25600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// - Exclusive - owned by a single thread, 25700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// - Shared(n) - shared amongst n threads. 25800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// 25900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// The effect of locking and unlocking operations on the state is: 26000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// 26100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// State | ExclusiveLock | ExclusiveUnlock | SharedLock | SharedUnlock 26200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// ---------------------------------------------------------------------------- 26300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// Free | Exclusive | error | SharedLock(1) | error 26400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// Exclusive | Block | Free | Block | error 26500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// Shared(n) | Block | error | SharedLock(n+1)* | Shared(n-1) or Free 26600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// * for large values of n the SharedLock may block. 26700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogersclass LOCKABLE ReaderWriterMutex : public BaseMutex { 2688daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes public: 26900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers explicit ReaderWriterMutex(const char* name, MutexLevel level = kDefaultMutexLevel); 27000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers ~ReaderWriterMutex(); 27100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers 27200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers virtual bool IsReaderWriterMutex() const { return true; } 27300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers 27400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // Block until ReaderWriterMutex is free then acquire exclusive access. 27500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers void ExclusiveLock() EXCLUSIVE_LOCK_FUNCTION(); 27600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers void WriterLock() EXCLUSIVE_LOCK_FUNCTION() { ExclusiveLock(); } 27700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers 27800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // Release exclusive access. 27900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers void ExclusiveUnlock() UNLOCK_FUNCTION(); 28000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers void WriterUnlock() UNLOCK_FUNCTION() { ExclusiveUnlock(); } 28100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers 28200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // Block until ReaderWriterMutex is free and acquire exclusive access. Returns true on success 28300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // or false if timeout is reached. 28466aee5cd571cf4739d2735769304202ea5051fb8Ian Rogers#if HAVE_TIMED_RWLOCK 28500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers bool ExclusiveLockWithTimeout(const timespec& abs_timeout) EXCLUSIVE_TRYLOCK_FUNCTION(true); 28666aee5cd571cf4739d2735769304202ea5051fb8Ian Rogers#endif 28700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers 28800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // Block until ReaderWriterMutex is shared or free then acquire a share on the access. 28900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers void SharedLock() SHARED_LOCK_FUNCTION(); 29000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers void ReaderLock() SHARED_LOCK_FUNCTION() { SharedLock(); } 29100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers 29200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // Try to acquire share of ReaderWriterMutex. 29300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers bool SharedTryLock() EXCLUSIVE_TRYLOCK_FUNCTION(true); 29400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers 29500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // Release a share of the access. 29600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers void SharedUnlock() UNLOCK_FUNCTION(); 29700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers void ReaderUnlock() UNLOCK_FUNCTION() { SharedUnlock(); } 29800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers 29900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // Is the current thread the exclusive holder of the ReaderWriterMutex. 30000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers bool IsExclusiveHeld() const; 30100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers 30200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // Assert the current thread has exclusive access to the ReaderWriterMutex. 30300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers void AssertExclusiveHeld() { 30425fd14b87cced64a179dee885573113be5e11944Ian Rogers if (kDebugLocking) { 30500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers CHECK(IsExclusiveHeld()); 30600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers } 3078daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes } 30800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers void AssertWriterHeld() { AssertExclusiveHeld(); } 3098daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes 31000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // Assert the current thread doesn't have exclusive access to the ReaderWriterMutex. 31100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers void AssertNotExclusiveHeld() { 31225fd14b87cced64a179dee885573113be5e11944Ian Rogers if (kDebugLocking) { 31300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers CHECK(!IsExclusiveHeld()); 31400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers } 31500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers } 31600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers void AssertNotWriterHeld() { AssertNotExclusiveHeld(); } 31700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers 31800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // Is the current thread a shared holder of the ReaderWriterMutex. 31900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers bool IsSharedHeld() const; 32000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers 32100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // Assert the current thread has shared access to the ReaderWriterMutex. 32200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers void AssertSharedHeld() { 32325fd14b87cced64a179dee885573113be5e11944Ian Rogers if (kDebugLocking) { 32400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers CHECK(IsSharedHeld()); 32500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers } 3268daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes } 32700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers void AssertReaderHeld() { AssertSharedHeld(); } 3288daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes 32900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // Assert the current thread doesn't hold this ReaderWriterMutex either in shared or exclusive 33000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // mode. 33100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers void AssertNotHeld() { 33225fd14b87cced64a179dee885573113be5e11944Ian Rogers if (kDebugLocking) { 33300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers CHECK(!IsSharedHeld()); 33400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers } 33500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers } 33600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers 33700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // Id associated with exclusive owner. 33800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers uint64_t GetExclusiveOwnerTid() const; 3398daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes private: 34000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers pthread_rwlock_t rwlock_; 34100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers 34200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers friend class MutexTester; 34300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers DISALLOW_COPY_AND_ASSIGN(ReaderWriterMutex); 3448daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes}; 3458daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes 34600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// ConditionVariables allow threads to queue and sleep. Threads may then be resumed individually 34700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// (Signal) or all at once (Broadcast). 3485f79133a435ebcb20000370d56046fe01201dd80Elliott Hughesclass ConditionVariable { 3495f79133a435ebcb20000370d56046fe01201dd80Elliott Hughes public: 350a51a3dd5603daf3d368b7735067e1d9eb54c4c40Elliott Hughes explicit ConditionVariable(const std::string& name); 3515f79133a435ebcb20000370d56046fe01201dd80Elliott Hughes ~ConditionVariable(); 3525f79133a435ebcb20000370d56046fe01201dd80Elliott Hughes 3535f79133a435ebcb20000370d56046fe01201dd80Elliott Hughes void Broadcast(); 3545f79133a435ebcb20000370d56046fe01201dd80Elliott Hughes void Signal(); 3555f79133a435ebcb20000370d56046fe01201dd80Elliott Hughes void Wait(Mutex& mutex); 3565f79133a435ebcb20000370d56046fe01201dd80Elliott Hughes void TimedWait(Mutex& mutex, const timespec& ts); 3575f79133a435ebcb20000370d56046fe01201dd80Elliott Hughes 3585f79133a435ebcb20000370d56046fe01201dd80Elliott Hughes private: 3595f79133a435ebcb20000370d56046fe01201dd80Elliott Hughes pthread_cond_t cond_; 3605f79133a435ebcb20000370d56046fe01201dd80Elliott Hughes std::string name_; 3615f79133a435ebcb20000370d56046fe01201dd80Elliott Hughes DISALLOW_COPY_AND_ASSIGN(ConditionVariable); 3625f79133a435ebcb20000370d56046fe01201dd80Elliott Hughes}; 3635f79133a435ebcb20000370d56046fe01201dd80Elliott Hughes 36400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// Scoped locker/unlocker for a regular Mutex that acquires mu upon construction and releases it 36500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// upon destruction. 36600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogersclass SCOPED_LOCKABLE MutexLock { 36700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers public: 36800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers explicit MutexLock(Mutex& mu) EXCLUSIVE_LOCK_FUNCTION(mu) : mu_(mu) { 36900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers mu_.ExclusiveLock(); 37000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers } 37100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers 37200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers ~MutexLock() UNLOCK_FUNCTION() { 37300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers mu_.ExclusiveUnlock(); 37400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers } 37500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers 37600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers private: 37700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers Mutex& mu_; 37800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers DISALLOW_COPY_AND_ASSIGN(MutexLock); 37900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers}; 38000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// Catch bug where variable name is omitted. "MutexLock (lock);" instead of "MutexLock mu(lock)". 38100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers#define MutexLock(x) COMPILE_ASSERT(0, mutex_lock_declaration_missing_variable_name) 38200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers 38300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// Scoped locker/unlocker for a ReaderWriterMutex that acquires read access to mu upon 38400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// construction and releases it upon destruction. 38500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogersclass SCOPED_LOCKABLE ReaderMutexLock { 38600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers public: 38700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers explicit ReaderMutexLock(ReaderWriterMutex& mu) EXCLUSIVE_LOCK_FUNCTION(mu) : mu_(mu) { 38800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers mu_.SharedLock(); 38900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers } 39000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers 39100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers ~ReaderMutexLock() UNLOCK_FUNCTION() { 39200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers mu_.SharedUnlock(); 39300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers } 39400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers 39500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers private: 39600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers ReaderWriterMutex& mu_; 39700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers DISALLOW_COPY_AND_ASSIGN(ReaderMutexLock); 39800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers}; 39900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// Catch bug where variable name is omitted. "ReaderMutexLock (lock);" instead of 40000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// "ReaderMutexLock mu(lock)". 40100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers#define ReaderMutexLock(x) COMPILE_ASSERT(0, reader_mutex_lock_declaration_missing_variable_name) 40200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers 40300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// Scoped locker/unlocker for a ReaderWriterMutex that acquires write access to mu upon 40400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// construction and releases it upon destruction. 40500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogersclass SCOPED_LOCKABLE WriterMutexLock { 40600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers public: 40700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers explicit WriterMutexLock(ReaderWriterMutex& mu) EXCLUSIVE_LOCK_FUNCTION(mu) : mu_(mu) { 40800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers mu_.ExclusiveLock(); 40900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers } 41000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers 41100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers ~WriterMutexLock() UNLOCK_FUNCTION() { 41200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers mu_.ExclusiveUnlock(); 41300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers } 41400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers 41500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers private: 41600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers ReaderWriterMutex& mu_; 41700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers DISALLOW_COPY_AND_ASSIGN(WriterMutexLock); 41800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers}; 41900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// Catch bug where variable name is omitted. "WriterMutexLock (lock);" instead of 42000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// "WriterMutexLock mu(lock)". 42100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers#define WriterMutexLock(x) COMPILE_ASSERT(0, writer_mutex_lock_declaration_missing_variable_name) 42200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers 42300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// Scoped unlocker/locker for a ReaderWriterMutex that releases read access to mu upon 42400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// construction and acquires it again upon destruction. 42500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogersclass ReaderMutexUnlock { 42600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers public: 42700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers explicit ReaderMutexUnlock(ReaderWriterMutex& mu) UNLOCK_FUNCTION(mu) : mu_(mu) { 42800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers mu_.SharedUnlock(); 42900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers } 43000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers 43100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers ~ReaderMutexUnlock() SHARED_LOCK_FUNCTION(mu_) { 43200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers mu_.SharedLock(); 43300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers } 43400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers 43500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers private: 43600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers ReaderWriterMutex& mu_; 43700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers DISALLOW_COPY_AND_ASSIGN(ReaderMutexUnlock); 43800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers}; 43900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// Catch bug where variable name is omitted. "ReaderMutexUnlock (lock);" instead of 44000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// "ReaderMutexUnlock mu(lock)". 44100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers#define ReaderMutexUnlock(x) \ 44200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers COMPILE_ASSERT(0, reader_mutex_unlock_declaration_missing_variable_name) 44300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers 4448daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes} // namespace art 4458daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes 4468daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes#endif // ART_SRC_MUTEX_H_ 447