| Mathias Agopian | 2bd9959 | 2012-02-25 23:02:14 -0800 | [diff] [blame] | 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 |  | 
| Yabin Cui | 4a6e5a3 | 2015-01-26 19:48:54 -0800 | [diff] [blame] | 24 | #if !defined(_WIN32) | 
| Mathias Agopian | 2bd9959 | 2012-02-25 23:02:14 -0800 | [diff] [blame] | 25 | # include <pthread.h> | 
|  | 26 | #endif | 
|  | 27 |  | 
|  | 28 | #include <utils/Errors.h> | 
| Jesse Hall | 601424a | 2014-12-23 14:00:29 -0800 | [diff] [blame] | 29 | #include <utils/Timers.h> | 
| Mathias Agopian | 2bd9959 | 2012-02-25 23:02:14 -0800 | [diff] [blame] | 30 |  | 
|  | 31 | // --------------------------------------------------------------------------- | 
|  | 32 | namespace android { | 
|  | 33 | // --------------------------------------------------------------------------- | 
|  | 34 |  | 
|  | 35 | class Condition; | 
|  | 36 |  | 
|  | 37 | /* | 
| Greg Kaiser | d62698d | 2016-04-05 10:55:13 -0700 | [diff] [blame] | 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 | * | 
| Mathias Agopian | 2bd9959 | 2012-02-25 23:02:14 -0800 | [diff] [blame] | 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 | */ | 
|  | 47 | class Mutex { | 
|  | 48 | public: | 
|  | 49 | enum { | 
|  | 50 | PRIVATE = 0, | 
|  | 51 | SHARED = 1 | 
|  | 52 | }; | 
| Jesse Hall | 601424a | 2014-12-23 14:00:29 -0800 | [diff] [blame] | 53 |  | 
| Mathias Agopian | 2bd9959 | 2012-02-25 23:02:14 -0800 | [diff] [blame] | 54 | Mutex(); | 
| Chih-Hung Hsieh | 2a92996 | 2016-08-02 12:14:47 -0700 | [diff] [blame] | 55 | explicit    Mutex(const char* name); | 
|  | 56 | explicit    Mutex(int type, const char* name = NULL); | 
| Mathias Agopian | 2bd9959 | 2012-02-25 23:02:14 -0800 | [diff] [blame] | 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 |  | 
| Elliott Hughes | 9b828ad | 2015-07-30 08:47:35 -0700 | [diff] [blame] | 66 | #if defined(__ANDROID__) | 
| Jesse Hall | 601424a | 2014-12-23 14:00:29 -0800 | [diff] [blame] | 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 |  | 
| Mathias Agopian | 2bd9959 | 2012-02-25 23:02:14 -0800 | [diff] [blame] | 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: | 
| Chih-Hung Hsieh | 2a92996 | 2016-08-02 12:14:47 -0700 | [diff] [blame] | 80 | inline explicit Autolock(Mutex& mutex) : mLock(mutex)  { mLock.lock(); } | 
|  | 81 | inline explicit Autolock(Mutex* mutex) : mLock(*mutex) { mLock.lock(); } | 
| Mathias Agopian | 2bd9959 | 2012-02-25 23:02:14 -0800 | [diff] [blame] | 82 | inline ~Autolock() { mLock.unlock(); } | 
|  | 83 | private: | 
|  | 84 | Mutex& mLock; | 
|  | 85 | }; | 
|  | 86 |  | 
|  | 87 | private: | 
|  | 88 | friend class Condition; | 
| Jesse Hall | 601424a | 2014-12-23 14:00:29 -0800 | [diff] [blame] | 89 |  | 
| Mathias Agopian | 2bd9959 | 2012-02-25 23:02:14 -0800 | [diff] [blame] | 90 | // A mutex cannot be copied | 
|  | 91 | Mutex(const Mutex&); | 
|  | 92 | Mutex&      operator = (const Mutex&); | 
| Jesse Hall | 601424a | 2014-12-23 14:00:29 -0800 | [diff] [blame] | 93 |  | 
| Yabin Cui | 4a6e5a3 | 2015-01-26 19:48:54 -0800 | [diff] [blame] | 94 | #if !defined(_WIN32) | 
| Mathias Agopian | 2bd9959 | 2012-02-25 23:02:14 -0800 | [diff] [blame] | 95 | pthread_mutex_t mMutex; | 
|  | 96 | #else | 
|  | 97 | void    _init(); | 
|  | 98 | void*   mState; | 
|  | 99 | #endif | 
|  | 100 | }; | 
|  | 101 |  | 
|  | 102 | // --------------------------------------------------------------------------- | 
|  | 103 |  | 
| Yabin Cui | 4a6e5a3 | 2015-01-26 19:48:54 -0800 | [diff] [blame] | 104 | #if !defined(_WIN32) | 
| Mathias Agopian | 2bd9959 | 2012-02-25 23:02:14 -0800 | [diff] [blame] | 105 |  | 
|  | 106 | inline Mutex::Mutex() { | 
|  | 107 | pthread_mutex_init(&mMutex, NULL); | 
|  | 108 | } | 
| Igor Murashkin | a27c1e0 | 2012-12-05 16:10:26 -0800 | [diff] [blame] | 109 | inline Mutex::Mutex(__attribute__((unused)) const char* name) { | 
| Mathias Agopian | 2bd9959 | 2012-02-25 23:02:14 -0800 | [diff] [blame] | 110 | pthread_mutex_init(&mMutex, NULL); | 
|  | 111 | } | 
| Igor Murashkin | a27c1e0 | 2012-12-05 16:10:26 -0800 | [diff] [blame] | 112 | inline Mutex::Mutex(int type, __attribute__((unused)) const char* name) { | 
| Mathias Agopian | 2bd9959 | 2012-02-25 23:02:14 -0800 | [diff] [blame] | 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 | } | 
|  | 123 | inline Mutex::~Mutex() { | 
|  | 124 | pthread_mutex_destroy(&mMutex); | 
|  | 125 | } | 
|  | 126 | inline status_t Mutex::lock() { | 
|  | 127 | return -pthread_mutex_lock(&mMutex); | 
|  | 128 | } | 
|  | 129 | inline void Mutex::unlock() { | 
|  | 130 | pthread_mutex_unlock(&mMutex); | 
|  | 131 | } | 
|  | 132 | inline status_t Mutex::tryLock() { | 
|  | 133 | return -pthread_mutex_trylock(&mMutex); | 
|  | 134 | } | 
| Elliott Hughes | 9b828ad | 2015-07-30 08:47:35 -0700 | [diff] [blame] | 135 | #if defined(__ANDROID__) | 
| Jesse Hall | 601424a | 2014-12-23 14:00:29 -0800 | [diff] [blame] | 136 | inline status_t Mutex::timedLock(nsecs_t timeoutNs) { | 
|  | 137 | const struct timespec ts = { | 
| Chih-Hung Hsieh | ba8cdf9 | 2015-01-12 16:21:46 -0800 | [diff] [blame] | 138 | /* .tv_sec = */ static_cast<time_t>(timeoutNs / 1000000000), | 
|  | 139 | /* .tv_nsec = */ static_cast<long>(timeoutNs % 1000000000), | 
| Jesse Hall | 601424a | 2014-12-23 14:00:29 -0800 | [diff] [blame] | 140 | }; | 
|  | 141 | return -pthread_mutex_timedlock(&mMutex, &ts); | 
|  | 142 | } | 
|  | 143 | #endif | 
| Mathias Agopian | 2bd9959 | 2012-02-25 23:02:14 -0800 | [diff] [blame] | 144 |  | 
| Yabin Cui | 4a6e5a3 | 2015-01-26 19:48:54 -0800 | [diff] [blame] | 145 | #endif // !defined(_WIN32) | 
| Mathias Agopian | 2bd9959 | 2012-02-25 23:02:14 -0800 | [diff] [blame] | 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 | */ | 
| Jesse Hall | 601424a | 2014-12-23 14:00:29 -0800 | [diff] [blame] | 154 |  | 
| Mathias Agopian | 2bd9959 | 2012-02-25 23:02:14 -0800 | [diff] [blame] | 155 | typedef Mutex::Autolock AutoMutex; | 
|  | 156 |  | 
|  | 157 | // --------------------------------------------------------------------------- | 
|  | 158 | }; // namespace android | 
|  | 159 | // --------------------------------------------------------------------------- | 
|  | 160 |  | 
|  | 161 | #endif // _LIBS_UTILS_MUTEX_H |