1 /* 2 * Copyright (C) 2007 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #ifndef _LIBS_UTILS_RWLOCK_H 18 #define _LIBS_UTILS_RWLOCK_H 19 20 #include <stdint.h> 21 #include <sys/types.h> 22 23 #if defined(HAVE_PTHREADS) 24 # include <pthread.h> 25 #endif 26 27 #include <utils/Errors.h> 28 #include <utils/ThreadDefs.h> 29 30 // --------------------------------------------------------------------------- 31 namespace android { 32 // --------------------------------------------------------------------------- 33 34 #if defined(HAVE_PTHREADS) 35 36 /* 37 * Simple mutex class. The implementation is system-dependent. 38 * 39 * The mutex must be unlocked by the thread that locked it. They are not 40 * recursive, i.e. the same thread can't lock it multiple times. 41 */ 42 class RWLock { 43 public: 44 enum { 45 PRIVATE = 0, 46 SHARED = 1 47 }; 48 49 RWLock(); 50 RWLock(const char* name); 51 RWLock(int type, const char* name = NULL); 52 ~RWLock(); 53 54 status_t readLock(); 55 status_t tryReadLock(); 56 status_t writeLock(); 57 status_t tryWriteLock(); 58 void unlock(); 59 60 class AutoRLock { 61 public: 62 inline AutoRLock(RWLock& rwlock) : mLock(rwlock) { mLock.readLock(); } 63 inline ~AutoRLock() { mLock.unlock(); } 64 private: 65 RWLock& mLock; 66 }; 67 68 class AutoWLock { 69 public: 70 inline AutoWLock(RWLock& rwlock) : mLock(rwlock) { mLock.writeLock(); } 71 inline ~AutoWLock() { mLock.unlock(); } 72 private: 73 RWLock& mLock; 74 }; 75 76 private: 77 // A RWLock cannot be copied 78 RWLock(const RWLock&); 79 RWLock& operator = (const RWLock&); 80 81 pthread_rwlock_t mRWLock; 82 }; 83 84 inline RWLock::RWLock() { 85 pthread_rwlock_init(&mRWLock, NULL); 86 } 87 inline RWLock::RWLock(__attribute__((unused)) const char* name) { 88 pthread_rwlock_init(&mRWLock, NULL); 89 } 90 inline RWLock::RWLock(int type, __attribute__((unused)) const char* name) { 91 if (type == SHARED) { 92 pthread_rwlockattr_t attr; 93 pthread_rwlockattr_init(&attr); 94 pthread_rwlockattr_setpshared(&attr, PTHREAD_PROCESS_SHARED); 95 pthread_rwlock_init(&mRWLock, &attr); 96 pthread_rwlockattr_destroy(&attr); 97 } else { 98 pthread_rwlock_init(&mRWLock, NULL); 99 } 100 } 101 inline RWLock::~RWLock() { 102 pthread_rwlock_destroy(&mRWLock); 103 } 104 inline status_t RWLock::readLock() { 105 return -pthread_rwlock_rdlock(&mRWLock); 106 } 107 inline status_t RWLock::tryReadLock() { 108 return -pthread_rwlock_tryrdlock(&mRWLock); 109 } 110 inline status_t RWLock::writeLock() { 111 return -pthread_rwlock_wrlock(&mRWLock); 112 } 113 inline status_t RWLock::tryWriteLock() { 114 return -pthread_rwlock_trywrlock(&mRWLock); 115 } 116 inline void RWLock::unlock() { 117 pthread_rwlock_unlock(&mRWLock); 118 } 119 120 #endif // HAVE_PTHREADS 121 122 // --------------------------------------------------------------------------- 123 }; // namespace android 124 // --------------------------------------------------------------------------- 125 126 #endif // _LIBS_UTILS_RWLOCK_H 127