mutex.h revision 00f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abac
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" 273efb8416c9809a1da3300509fd9d2bc54e22e4c2Elliott Hughes#include "gtest/gtest.h" 288daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes#include "logging.h" 298daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes#include "macros.h" 308daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes 318daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughesnamespace art { 328daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes 3300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogersclass LOCKABLE Mutex; 3400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogersclass LOCKABLE ReaderWriterMutex; 3500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers 3600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// MutexLevel is used to impose a lock hierarchy [1] where acquisition of a Mutex at a higher or 3700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// equal level to a lock a thread holds is invalid. The lock hierarchy achieves a cycle free 3800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// partial ordering and thereby cause deadlock situations to fail checks. 3900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// 4000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// [1] http://www.drdobbs.com/parallel/use-lock-hierarchies-to-avoid-deadlock/204801163 4100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogersenum MutexLevel { 4200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers kLoggingLock = 0, 4300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers kUnexpectedSignalLock = 1, 44ffb465f23d9549dd591e6aa62e9250523cb00233Elliott Hughes kThreadSuspendCountLock = 2, 4500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers kAbortLock = 3, 4600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers kDefaultMutexLevel = 4, 4700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers kLoadLibraryLock = 5, 4800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers kClassLinkerClassesLock = 6, 4900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers kThreadListLock = 7, 5000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers kHeapBitmapLock = 8, 5100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers kZygoteCreationLock = 9, 5200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers kMonitorLock = 10, 5300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers kMutatorLock = 11, 5400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers kMaxMutexLevel = kMutatorLock, 55ffb465f23d9549dd591e6aa62e9250523cb00233Elliott Hughes}; 5600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogersstd::ostream& operator<<(std::ostream& os, const MutexLevel& rhs); 57ffb465f23d9549dd591e6aa62e9250523cb00233Elliott Hughes 5800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// Global mutexes corresponding to the levels above. 5900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogersclass GlobalSynchronization { 608daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes public: 6100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers static void Init(); 628daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes 6300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // The mutator_lock_ is used to allow mutators to execute in a shared (reader) mode or to block 6400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // mutators by having an exclusive (writer) owner. In normal execution each mutator thread holds 6500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // a share on the mutator_lock_. The garbage collector may also execute with shared access but 6600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // at times requires exclusive access to the heap (not to be confused with the heap meta-data 6700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // guarded by the heap_lock_ below). When the garbage collector requires exclusive access it asks 6800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // the mutators to suspend themselves which also involves usage of the thread_suspend_count_lock_ 6900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // to cover weaknesses in using ReaderWriterMutexes with ConditionVariables. We use a condition 7000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // variable to wait upon in the suspension logic as releasing and then re-acquiring a share on 7100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // the mutator lock doesn't necessarily allow the exclusive user (e.g the garbage collector) 7200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // chance to acquire the lock. 7300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // 7400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // Thread suspension: 7500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // Shared users | Exclusive user 7600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // (holding mutator lock and in kRunnable state) | .. running .. 7700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // .. running .. | Request thread suspension by: 7800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // .. running .. | - acquiring thread_suspend_count_lock_ 7900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // .. running .. | - incrementing Thread::suspend_count_ on 8000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // .. running .. | all mutator threads 8100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // .. running .. | - releasing thread_suspend_count_lock_ 8200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // .. running .. | Block trying to acquire exclusive mutator lock 8300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // Poll Thread::suspend_count_ and enter full | .. blocked .. 8400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // suspend code. | .. blocked .. 8500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // Change state to kSuspended | .. blocked .. 8600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // x: Release share on mutator_lock_ | Carry out exclusive access 8700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // Acquire thread_suspend_count_lock_ | .. exclusive .. 8800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // while Thread::suspend_count_ > 0 | .. exclusive .. 8900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // - wait on Thread::resume_cond_ | .. exclusive .. 9000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // (releases thread_suspend_count_lock_) | .. exclusive .. 9100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // .. waiting .. | Release mutator_lock_ 9200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // .. waiting .. | Request thread resumption by: 9300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // .. waiting .. | - acquiring thread_suspend_count_lock_ 9400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // .. waiting .. | - decrementing Thread::suspend_count_ on 9500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // .. waiting .. | all mutator threads 9600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // .. waiting .. | - notifying on Thread::resume_cond_ 9700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // - re-acquire thread_suspend_count_lock_ | - releasing thread_suspend_count_lock_ 9800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // Release thread_suspend_count_lock_ | .. running .. 9900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // Acquire share on mutator_lock_ | .. running .. 10000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // - This could block but the thread still | .. running .. 10100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // has a state of kSuspended and so this | .. running .. 10200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // isn't an issue. | .. running .. 10300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // Acquire thread_suspend_count_lock_ | .. running .. 10400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // - we poll here as we're transitioning into | .. running .. 10500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // kRunnable and an individual thread suspend | .. running .. 10600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // request (e.g for debugging) won't try | .. running .. 10700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // to acquire the mutator lock (which would | .. running .. 10800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // block as we hold the mutator lock). This | .. running .. 10900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // poll ensures that if the suspender thought | .. running .. 11000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // we were suspended by incrementing our | .. running .. 11100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // Thread::suspend_count_ and then reading | .. running .. 11200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // our state we go back to waiting on | .. running .. 11300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // Thread::resume_cond_. | .. running .. 11400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // can_go_runnable = Thread::suspend_count_ == 0 | .. running .. 11500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // Release thread_suspend_count_lock_ | .. running .. 11600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // if can_go_runnable | .. running .. 11700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // Change state to kRunnable | .. running .. 11800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // else | .. running .. 11900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // Goto x | .. running .. 12000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // .. running .. | .. running .. 12100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers static ReaderWriterMutex* mutator_lock_; 1228daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes 12300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // Allow reader-writer mutual exclusion on the mark and live bitmaps of the heap. 12400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers static ReaderWriterMutex* heap_bitmap_lock_ ACQUIRED_AFTER(mutator_lock_); 1258daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes 12600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // The thread_list_lock_ guards ThreadList::list_. It is also commonly held to stop threads 12700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // attaching and detaching. 12800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers static Mutex* thread_list_lock_ ACQUIRED_AFTER(heap_bitmap_lock_); 1298daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes 13000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // Guards lists of classes within the class linker. 13100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers static Mutex* classlinker_classes_lock_ ACQUIRED_AFTER(thread_list_lock_); 1328daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes 13300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // When declaring any Mutex add DEFAULT_MUTEX_ACQUIRED_AFTER to use annotalysis to check the code 13400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // doesn't try to hold a higher level Mutex. 13500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers #define DEFAULT_MUTEX_ACQUIRED_AFTER ACQUIRED_AFTER(classlinker_classes_lock_) 136accd83d1523545ac69bafd38e72a7d5cff8e2facElliott Hughes 13700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // Have an exclusive aborting thread. 13800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers static Mutex* abort_lock_ ACQUIRED_AFTER(classlinker_classes_lock_); 139cd74c4b3a6893c876c6e03fd99a1264249653d80Brian Carlstrom 14000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // Allow mutual exclusion when manipulating Thread::suspend_count_. 14100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // TODO: Does the trade-off of a per-thread lock make sense? 14200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers static Mutex* thread_suspend_count_lock_ ACQUIRED_AFTER(abort_lock_); 14300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers 14400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // One unexpected signal at a time lock. 14500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers static Mutex* unexpected_signal_lock_ ACQUIRED_AFTER(thread_suspend_count_lock_); 14600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers 14700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // Have an exclusive logging thread. 14800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers static Mutex* logging_lock_ ACQUIRED_AFTER(unexpected_signal_lock_); 14900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers}; 15000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers 15100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// Base class for all Mutex implementations 15200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogersclass BaseMutex { 15300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers public: 15400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers const std::string& GetName() const { 15500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers return name_; 15600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers } 15700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers 15800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers virtual bool IsMutex() const { return false; } 15900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers virtual bool IsReaderWriterMutex() const { return false; } 16000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers 16100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers protected: 16200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers friend class ConditionVariable; 16300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers 16400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers BaseMutex(const char* name, MutexLevel level); 16500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers virtual ~BaseMutex() {} 16600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers void RegisterAsLockedWithCurrentThread(); 16700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers void RegisterAsUnlockedWithCurrentThread(); 16800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers void CheckSafeToWait(); 16900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers 17000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers const MutexLevel level_; // Support for lock hierarchy. 1710a1038b0a30a52dff1a449a989825e808a83df80Elliott Hughes const std::string name_; 17200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers}; 17300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers 17400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// A Mutex is used to achieve mutual exclusion between threads. A Mutex can be used to gain 17500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// exclusive access to what it guards. A Mutex can be in one of two states: 17600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// - Free - not owned by any thread, 17700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// - Exclusive - owned by a single thread. 17800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// 17900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// The effect of locking and unlocking operations on the state is: 18000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// State | ExclusiveLock | ExclusiveUnlock 18100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// ------------------------------------------- 18200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// Free | Exclusive | error 18300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// Exclusive | Block* | Free 18400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// * Mutex is not reentrant and so an attempt to ExclusiveLock on the same thread will result in 18500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// an error. Being non-reentrant simplifies Waiting on ConditionVariables. 18600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogersclass LOCKABLE Mutex : public BaseMutex { 18700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers public: 18800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers explicit Mutex(const char* name, MutexLevel level = kDefaultMutexLevel, bool recursive = false); 18900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers ~Mutex(); 19000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers 19100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers virtual bool IsMutex() const { return true; } 19200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers 19300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // Block until mutex is free then acquire exclusive access. 19400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers void ExclusiveLock() EXCLUSIVE_LOCK_FUNCTION(); 19500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers void Lock() EXCLUSIVE_LOCK_FUNCTION() { ExclusiveLock(); } 19600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers 19700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // Returns true if acquires exclusive access, false otherwise. 19800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers bool ExclusiveTryLock() EXCLUSIVE_TRYLOCK_FUNCTION(true); 19900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers bool TryLock() EXCLUSIVE_TRYLOCK_FUNCTION(true) { return ExclusiveTryLock(); } 20000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers 20100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // Release exclusive access. 20200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers void ExclusiveUnlock() UNLOCK_FUNCTION(); 20300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers void Unlock() UNLOCK_FUNCTION() { ExclusiveUnlock(); } 20400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers 20500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // Is the current thread the exclusive holder of the Mutex. 20600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers bool IsExclusiveHeld() const; 2078daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes 20800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // Assert that the Mutex is exclusively held by the current thread. 20900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers void AssertExclusiveHeld() { 21000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers if (kIsDebugBuild) { 21100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers CHECK(IsExclusiveHeld()); 21200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers } 21300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers } 21400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers void AssertHeld() { AssertExclusiveHeld(); } 21500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers 21600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // Assert that the Mutex is not held by the current thread. 21700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers void AssertNotHeldExclusive() { 21800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers if (kIsDebugBuild) { 21900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers CHECK(!IsExclusiveHeld()); 22000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers } 22100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers } 22200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers void AssertNotHeld() { AssertNotHeldExclusive(); } 22300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers 22400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // Id associated with exclusive owner. 22500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers uint64_t GetExclusiveOwnerTid() const; 22600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers 22700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // Returns how many times this Mutex has been locked, it is better to use AssertHeld/NotHeld. 22800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers unsigned int GetDepth() const { 22900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers return recursion_count_; 23000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers } 23100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers 23200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers private: 23300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers pthread_mutex_t mutex_; 23400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers const bool recursive_; // Can the lock be recursively held? 23500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers unsigned int recursion_count_; 236f1498437b0d6beb9f4f91980b98cbeb0b5c773ceElliott Hughes friend class ConditionVariable; 2373efb8416c9809a1da3300509fd9d2bc54e22e4c2Elliott Hughes friend class MutexTester; 2388daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes DISALLOW_COPY_AND_ASSIGN(Mutex); 2398daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes}; 2408daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes 24100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// A ReaderWriterMutex is used to achieve mutual exclusion between threads, similar to a Mutex. 24200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// Unlike a Mutex a ReaderWriterMutex can be used to gain exclusive (writer) or shared (reader) 24300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// access to what it guards. A flaw in relation to a Mutex is that it cannot be used with a 24400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// condition variable. A ReaderWriterMutex can be in one of three states: 24500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// - Free - not owned by any thread, 24600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// - Exclusive - owned by a single thread, 24700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// - Shared(n) - shared amongst n threads. 24800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// 24900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// The effect of locking and unlocking operations on the state is: 25000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// 25100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// State | ExclusiveLock | ExclusiveUnlock | SharedLock | SharedUnlock 25200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// ---------------------------------------------------------------------------- 25300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// Free | Exclusive | error | SharedLock(1) | error 25400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// Exclusive | Block | Free | Block | error 25500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// Shared(n) | Block | error | SharedLock(n+1)* | Shared(n-1) or Free 25600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// * for large values of n the SharedLock may block. 25700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogersclass LOCKABLE ReaderWriterMutex : public BaseMutex { 2588daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes public: 25900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers explicit ReaderWriterMutex(const char* name, MutexLevel level = kDefaultMutexLevel); 26000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers ~ReaderWriterMutex(); 26100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers 26200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers virtual bool IsReaderWriterMutex() const { return true; } 26300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers 26400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // Block until ReaderWriterMutex is free then acquire exclusive access. 26500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers void ExclusiveLock() EXCLUSIVE_LOCK_FUNCTION(); 26600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers void WriterLock() EXCLUSIVE_LOCK_FUNCTION() { ExclusiveLock(); } 26700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers 26800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // Release exclusive access. 26900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers void ExclusiveUnlock() UNLOCK_FUNCTION(); 27000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers void WriterUnlock() UNLOCK_FUNCTION() { ExclusiveUnlock(); } 27100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers 27200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // Block until ReaderWriterMutex is free and acquire exclusive access. Returns true on success 27300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // or false if timeout is reached. 27400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers bool ExclusiveLockWithTimeout(const timespec& abs_timeout) EXCLUSIVE_TRYLOCK_FUNCTION(true); 27500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers 27600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // Block until ReaderWriterMutex is shared or free then acquire a share on the access. 27700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers void SharedLock() SHARED_LOCK_FUNCTION(); 27800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers void ReaderLock() SHARED_LOCK_FUNCTION() { SharedLock(); } 27900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers 28000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // Try to acquire share of ReaderWriterMutex. 28100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers bool SharedTryLock() EXCLUSIVE_TRYLOCK_FUNCTION(true); 28200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers 28300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // Release a share of the access. 28400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers void SharedUnlock() UNLOCK_FUNCTION(); 28500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers void ReaderUnlock() UNLOCK_FUNCTION() { SharedUnlock(); } 28600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers 28700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // Is the current thread the exclusive holder of the ReaderWriterMutex. 28800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers bool IsExclusiveHeld() const; 28900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers 29000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // Assert the current thread has exclusive access to the ReaderWriterMutex. 29100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers void AssertExclusiveHeld() { 29200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers if (kIsDebugBuild) { 29300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers CHECK(IsExclusiveHeld()); 29400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers } 2958daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes } 29600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers void AssertWriterHeld() { AssertExclusiveHeld(); } 2978daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes 29800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // Assert the current thread doesn't have exclusive access to the ReaderWriterMutex. 29900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers void AssertNotExclusiveHeld() { 30000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers if (kIsDebugBuild) { 30100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers CHECK(!IsExclusiveHeld()); 30200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers } 30300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers } 30400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers void AssertNotWriterHeld() { AssertNotExclusiveHeld(); } 30500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers 30600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // Is the current thread a shared holder of the ReaderWriterMutex. 30700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers bool IsSharedHeld() const; 30800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers 30900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // Assert the current thread has shared access to the ReaderWriterMutex. 31000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers void AssertSharedHeld() { 31100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers if (kIsDebugBuild) { 31200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers CHECK(IsSharedHeld()); 31300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers } 3148daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes } 31500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers void AssertReaderHeld() { AssertSharedHeld(); } 3168daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes 31700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // Assert the current thread doesn't hold this ReaderWriterMutex either in shared or exclusive 31800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // mode. 31900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers void AssertNotHeld() { 32000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers if (kIsDebugBuild) { 32100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers CHECK(!IsSharedHeld()); 32200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers } 32300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers } 32400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers 32500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // Id associated with exclusive owner. 32600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers uint64_t GetExclusiveOwnerTid() const; 3278daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes private: 32800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers pthread_rwlock_t rwlock_; 32900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers 33000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers friend class MutexTester; 33100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers DISALLOW_COPY_AND_ASSIGN(ReaderWriterMutex); 3328daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes}; 3338daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes 33400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// ConditionVariables allow threads to queue and sleep. Threads may then be resumed individually 33500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// (Signal) or all at once (Broadcast). 3365f79133a435ebcb20000370d56046fe01201dd80Elliott Hughesclass ConditionVariable { 3375f79133a435ebcb20000370d56046fe01201dd80Elliott Hughes public: 338a51a3dd5603daf3d368b7735067e1d9eb54c4c40Elliott Hughes explicit ConditionVariable(const std::string& name); 3395f79133a435ebcb20000370d56046fe01201dd80Elliott Hughes ~ConditionVariable(); 3405f79133a435ebcb20000370d56046fe01201dd80Elliott Hughes 3415f79133a435ebcb20000370d56046fe01201dd80Elliott Hughes void Broadcast(); 3425f79133a435ebcb20000370d56046fe01201dd80Elliott Hughes void Signal(); 3435f79133a435ebcb20000370d56046fe01201dd80Elliott Hughes void Wait(Mutex& mutex); 3445f79133a435ebcb20000370d56046fe01201dd80Elliott Hughes void TimedWait(Mutex& mutex, const timespec& ts); 3455f79133a435ebcb20000370d56046fe01201dd80Elliott Hughes 3465f79133a435ebcb20000370d56046fe01201dd80Elliott Hughes private: 3475f79133a435ebcb20000370d56046fe01201dd80Elliott Hughes pthread_cond_t cond_; 3485f79133a435ebcb20000370d56046fe01201dd80Elliott Hughes std::string name_; 3495f79133a435ebcb20000370d56046fe01201dd80Elliott Hughes DISALLOW_COPY_AND_ASSIGN(ConditionVariable); 3505f79133a435ebcb20000370d56046fe01201dd80Elliott Hughes}; 3515f79133a435ebcb20000370d56046fe01201dd80Elliott Hughes 35200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// Scoped locker/unlocker for a regular Mutex that acquires mu upon construction and releases it 35300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// upon destruction. 35400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogersclass SCOPED_LOCKABLE MutexLock { 35500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers public: 35600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers explicit MutexLock(Mutex& mu) EXCLUSIVE_LOCK_FUNCTION(mu) : mu_(mu) { 35700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers mu_.ExclusiveLock(); 35800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers } 35900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers 36000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers ~MutexLock() UNLOCK_FUNCTION() { 36100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers mu_.ExclusiveUnlock(); 36200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers } 36300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers 36400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers private: 36500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers Mutex& mu_; 36600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers DISALLOW_COPY_AND_ASSIGN(MutexLock); 36700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers}; 36800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// Catch bug where variable name is omitted. "MutexLock (lock);" instead of "MutexLock mu(lock)". 36900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers#define MutexLock(x) COMPILE_ASSERT(0, mutex_lock_declaration_missing_variable_name) 37000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers 37100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// Scoped locker/unlocker for a ReaderWriterMutex that acquires read access to mu upon 37200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// construction and releases it upon destruction. 37300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogersclass SCOPED_LOCKABLE ReaderMutexLock { 37400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers public: 37500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers explicit ReaderMutexLock(ReaderWriterMutex& mu) EXCLUSIVE_LOCK_FUNCTION(mu) : mu_(mu) { 37600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers mu_.SharedLock(); 37700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers } 37800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers 37900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers ~ReaderMutexLock() UNLOCK_FUNCTION() { 38000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers mu_.SharedUnlock(); 38100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers } 38200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers 38300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers private: 38400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers ReaderWriterMutex& mu_; 38500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers DISALLOW_COPY_AND_ASSIGN(ReaderMutexLock); 38600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers}; 38700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// Catch bug where variable name is omitted. "ReaderMutexLock (lock);" instead of 38800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// "ReaderMutexLock mu(lock)". 38900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers#define ReaderMutexLock(x) COMPILE_ASSERT(0, reader_mutex_lock_declaration_missing_variable_name) 39000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers 39100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// Scoped locker/unlocker for a ReaderWriterMutex that acquires write access to mu upon 39200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// construction and releases it upon destruction. 39300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogersclass SCOPED_LOCKABLE WriterMutexLock { 39400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers public: 39500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers explicit WriterMutexLock(ReaderWriterMutex& mu) EXCLUSIVE_LOCK_FUNCTION(mu) : mu_(mu) { 39600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers mu_.ExclusiveLock(); 39700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers } 39800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers 39900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers ~WriterMutexLock() UNLOCK_FUNCTION() { 40000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers mu_.ExclusiveUnlock(); 40100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers } 40200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers 40300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers private: 40400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers ReaderWriterMutex& mu_; 40500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers DISALLOW_COPY_AND_ASSIGN(WriterMutexLock); 40600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers}; 40700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// Catch bug where variable name is omitted. "WriterMutexLock (lock);" instead of 40800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// "WriterMutexLock mu(lock)". 40900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers#define WriterMutexLock(x) COMPILE_ASSERT(0, writer_mutex_lock_declaration_missing_variable_name) 41000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers 41100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// Scoped unlocker/locker for a ReaderWriterMutex that releases read access to mu upon 41200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// construction and acquires it again upon destruction. 41300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogersclass ReaderMutexUnlock { 41400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers public: 41500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers explicit ReaderMutexUnlock(ReaderWriterMutex& mu) UNLOCK_FUNCTION(mu) : mu_(mu) { 41600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers mu_.SharedUnlock(); 41700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers } 41800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers 41900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers ~ReaderMutexUnlock() SHARED_LOCK_FUNCTION(mu_) { 42000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers mu_.SharedLock(); 42100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers } 42200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers 42300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers private: 42400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers ReaderWriterMutex& mu_; 42500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers DISALLOW_COPY_AND_ASSIGN(ReaderMutexUnlock); 42600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers}; 42700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// Catch bug where variable name is omitted. "ReaderMutexUnlock (lock);" instead of 42800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// "ReaderMutexUnlock mu(lock)". 42900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers#define ReaderMutexUnlock(x) \ 43000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers COMPILE_ASSERT(0, reader_mutex_unlock_declaration_missing_variable_name) 43100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers 4328daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes} // namespace art 4338daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes 4348daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes#endif // ART_SRC_MUTEX_H_ 435