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_MUTEX_H 18#define _LIBS_UTILS_MUTEX_H 19 20#include <stdint.h> 21#include <sys/types.h> 22#include <time.h> 23 24#if !defined(_WIN32) 25# include <pthread.h> 26#endif 27 28#include <utils/Errors.h> 29#include <utils/Timers.h> 30 31// --------------------------------------------------------------------------- 32namespace android { 33// --------------------------------------------------------------------------- 34 35class Condition; 36 37/* 38 * NOTE: This class is for code that builds on Win32. Its usage is 39 * deprecated for code which doesn't build for Win32. New code which 40 * doesn't build for Win32 should use std::mutex and std::lock_guard instead. 41 * 42 * Simple mutex class. The implementation is system-dependent. 43 * 44 * The mutex must be unlocked by the thread that locked it. They are not 45 * recursive, i.e. the same thread can't lock it multiple times. 46 */ 47class Mutex { 48public: 49 enum { 50 PRIVATE = 0, 51 SHARED = 1 52 }; 53 54 Mutex(); 55 Mutex(const char* name); 56 Mutex(int type, const char* name = NULL); 57 ~Mutex(); 58 59 // lock or unlock the mutex 60 status_t lock(); 61 void unlock(); 62 63 // lock if possible; returns 0 on success, error otherwise 64 status_t tryLock(); 65 66#if defined(__ANDROID__) 67 // lock the mutex, but don't wait longer than timeoutMilliseconds. 68 // Returns 0 on success, TIMED_OUT for failure due to timeout expiration. 69 // 70 // OSX doesn't have pthread_mutex_timedlock() or equivalent. To keep 71 // capabilities consistent across host OSes, this method is only available 72 // when building Android binaries. 73 status_t timedLock(nsecs_t timeoutMilliseconds); 74#endif 75 76 // Manages the mutex automatically. It'll be locked when Autolock is 77 // constructed and released when Autolock goes out of scope. 78 class Autolock { 79 public: 80 inline Autolock(Mutex& mutex) : mLock(mutex) { mLock.lock(); } 81 inline Autolock(Mutex* mutex) : mLock(*mutex) { mLock.lock(); } 82 inline ~Autolock() { mLock.unlock(); } 83 private: 84 Mutex& mLock; 85 }; 86 87private: 88 friend class Condition; 89 90 // A mutex cannot be copied 91 Mutex(const Mutex&); 92 Mutex& operator = (const Mutex&); 93 94#if !defined(_WIN32) 95 pthread_mutex_t mMutex; 96#else 97 void _init(); 98 void* mState; 99#endif 100}; 101 102// --------------------------------------------------------------------------- 103 104#if !defined(_WIN32) 105 106inline Mutex::Mutex() { 107 pthread_mutex_init(&mMutex, NULL); 108} 109inline Mutex::Mutex(__attribute__((unused)) const char* name) { 110 pthread_mutex_init(&mMutex, NULL); 111} 112inline Mutex::Mutex(int type, __attribute__((unused)) const char* name) { 113 if (type == SHARED) { 114 pthread_mutexattr_t attr; 115 pthread_mutexattr_init(&attr); 116 pthread_mutexattr_setpshared(&attr, PTHREAD_PROCESS_SHARED); 117 pthread_mutex_init(&mMutex, &attr); 118 pthread_mutexattr_destroy(&attr); 119 } else { 120 pthread_mutex_init(&mMutex, NULL); 121 } 122} 123inline Mutex::~Mutex() { 124 pthread_mutex_destroy(&mMutex); 125} 126inline status_t Mutex::lock() { 127 return -pthread_mutex_lock(&mMutex); 128} 129inline void Mutex::unlock() { 130 pthread_mutex_unlock(&mMutex); 131} 132inline status_t Mutex::tryLock() { 133 return -pthread_mutex_trylock(&mMutex); 134} 135#if defined(__ANDROID__) 136inline status_t Mutex::timedLock(nsecs_t timeoutNs) { 137 const struct timespec ts = { 138 /* .tv_sec = */ static_cast<time_t>(timeoutNs / 1000000000), 139 /* .tv_nsec = */ static_cast<long>(timeoutNs % 1000000000), 140 }; 141 return -pthread_mutex_timedlock(&mMutex, &ts); 142} 143#endif 144 145#endif // !defined(_WIN32) 146 147// --------------------------------------------------------------------------- 148 149/* 150 * Automatic mutex. Declare one of these at the top of a function. 151 * When the function returns, it will go out of scope, and release the 152 * mutex. 153 */ 154 155typedef Mutex::Autolock AutoMutex; 156 157// --------------------------------------------------------------------------- 158}; // namespace android 159// --------------------------------------------------------------------------- 160 161#endif // _LIBS_UTILS_MUTEX_H 162