1/* 2 * Copyright (c) 2011 Apple Inc. All rights reserved. 3 * 4 * @APPLE_APACHE_LICENSE_HEADER_START@ 5 * 6 * Licensed under the Apache License, Version 2.0 (the "License"); 7 * you may not use this file except in compliance with the License. 8 * You may obtain a copy of the License at 9 * 10 * http://www.apache.org/licenses/LICENSE-2.0 11 * 12 * Unless required by applicable law or agreed to in writing, software 13 * distributed under the License is distributed on an "AS IS" BASIS, 14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 * See the License for the specific language governing permissions and 16 * limitations under the License. 17 * 18 * @APPLE_APACHE_LICENSE_HEADER_END@ 19 */ 20/* 21 Locks.h 22 Scoped Locking Primitives 23 Copyright (c) 2004-2011 Apple Inc. All rights reserved. 24 */ 25 26#pragma once 27#ifndef __AUTO_LOCK__ 28#define __AUTO_LOCK__ 29 30 31#include <assert.h> 32 33#include "Definitions.h" 34#include "auto_impl_utilities.h" 35 36namespace Auto { 37 38 //----- LockedBoolean -----// 39 40 // Interlocked Boolean value. 41 42 struct LockedBoolean { 43 volatile bool state; 44 spin_lock_t lock; 45 LockedBoolean() : state(false), lock(0) {} 46 }; 47 48 //----- SpinLock -----// 49 50 // Scoped uses of spin_lock() / spin_unlock(). 51 52 class SpinLock { 53 spin_lock_t *_lock; 54 public: 55 SpinLock(spin_lock_t *lock) : _lock(lock) { spin_lock(_lock); } 56 ~SpinLock() { spin_unlock(_lock); } 57 }; 58 59 class TrySpinLock { 60 spin_lock_t *_lock; 61 public: 62 TrySpinLock(spin_lock_t *lock) : _lock(lock) { if (_lock && !spin_lock_try(_lock)) _lock = NULL; } 63 operator int() { return (_lock != NULL); } 64 ~TrySpinLock() { if (_lock) spin_unlock(_lock); } 65 }; 66 67 // Scoped conditional uses of spin_lock() / spin_unlock(). 68 69 class ConditionBarrier { 70 private: 71 spin_lock_t *_lock; 72 73 void check(bool volatile *condition, spin_lock_t *lock) { 74 if (*condition) { 75 spin_lock(lock); 76 if (!*condition) { 77 spin_unlock(lock); 78 } else { 79 _lock = lock; 80 } 81 } 82 } 83 public: 84 ConditionBarrier(bool volatile *condition, spin_lock_t *lock) : _lock(NULL) { 85 check(condition, lock); 86 } 87 ConditionBarrier(LockedBoolean &condition) : _lock(NULL) { 88 check(&condition.state, &condition.lock); 89 } 90 operator int() { return _lock != NULL; } 91 ~ConditionBarrier() { if (_lock) spin_unlock(_lock); } 92 }; 93 94 class UnconditionalBarrier { 95 bool volatile *_condition; 96 spin_lock_t *_lock; 97 public: 98 UnconditionalBarrier(bool volatile *condition, spin_lock_t *lock) : _condition(condition), _lock(lock) { 99 spin_lock(_lock); 100 } 101 UnconditionalBarrier(LockedBoolean &condition) : _condition(&condition.state), _lock(&condition.lock) { 102 spin_lock(_lock); 103 } 104 operator int() { return (*_condition != false); } 105 ~UnconditionalBarrier() { spin_unlock(_lock); } 106 }; 107 108 // Scoped uses of pthread_mutex_t. 109 110 class Mutex { 111 pthread_mutex_t *_mutex; 112 public: 113 Mutex(pthread_mutex_t *mutex) : _mutex(mutex) { if (_mutex) pthread_mutex_lock(_mutex); } 114 ~Mutex() { if (_mutex) pthread_mutex_unlock(_mutex); } 115 }; 116 117 class TryMutex { 118 pthread_mutex_t *_mutex; 119 public: 120 TryMutex(pthread_mutex_t *mutex) : _mutex(mutex) { if (_mutex && pthread_mutex_trylock(_mutex) != 0) _mutex = NULL; } 121 operator int() { return (_mutex != NULL); } 122 ~TryMutex() { if (_mutex) pthread_mutex_unlock(_mutex); } 123 }; 124 125 class ReadLock { 126 pthread_rwlock_t *_lock; 127 public: 128 ReadLock(pthread_rwlock_t *lock) : _lock(lock) { if (_lock) pthread_rwlock_rdlock(_lock); } 129 ~ReadLock() { if (_lock) pthread_rwlock_unlock(_lock); } 130 }; 131 132 class WriteLock { 133 pthread_rwlock_t *_lock; 134 public: 135 WriteLock(pthread_rwlock_t *lock) : _lock(lock) { if (_lock) pthread_rwlock_wrlock(_lock); } 136 ~WriteLock() { if (_lock) pthread_rwlock_unlock(_lock); } 137 }; 138 139 class TryWriteLock { 140 pthread_rwlock_t *_lock; 141 public: 142 TryWriteLock(pthread_rwlock_t *lock) : _lock(lock) { if (_lock && pthread_rwlock_trywrlock(_lock) != 0) _lock = NULL; } 143 operator int() { return (_lock != NULL); } 144 ~TryWriteLock() { if (_lock) pthread_rwlock_unlock(_lock); } 145 }; 146 147 typedef uint32_t sentinel_t; 148#define SENTINEL_T_INITIALIZER 0 149 150 class Sentinel { 151 sentinel_t &_guard; 152 public: 153 Sentinel(sentinel_t &guard) : _guard(guard) { 154 _guard++; 155 } 156 157 ~Sentinel() { _guard--; } 158 159 inline static boolean_t is_guarded(sentinel_t &guard) { return guard != 0; } 160 inline static void assert_guarded(sentinel_t &guard) { assert(is_guarded(guard)); } 161 }; 162}; 163 164#endif // __AUTO_LOCK__ 165