| 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 | /* | 
 | 38 |  * Simple mutex class.  The implementation is system-dependent. | 
 | 39 |  * | 
 | 40 |  * The mutex must be unlocked by the thread that locked it.  They are not | 
 | 41 |  * recursive, i.e. the same thread can't lock it multiple times. | 
 | 42 |  */ | 
 | 43 | class Mutex { | 
 | 44 | public: | 
 | 45 |     enum { | 
 | 46 |         PRIVATE = 0, | 
 | 47 |         SHARED = 1 | 
 | 48 |     }; | 
| Jesse Hall | 601424a | 2014-12-23 14:00:29 -0800 | [diff] [blame] | 49 |  | 
| Mathias Agopian | 2bd9959 | 2012-02-25 23:02:14 -0800 | [diff] [blame] | 50 |                 Mutex(); | 
 | 51 |                 Mutex(const char* name); | 
 | 52 |                 Mutex(int type, const char* name = NULL); | 
 | 53 |                 ~Mutex(); | 
 | 54 |  | 
 | 55 |     // lock or unlock the mutex | 
 | 56 |     status_t    lock(); | 
 | 57 |     void        unlock(); | 
 | 58 |  | 
 | 59 |     // lock if possible; returns 0 on success, error otherwise | 
 | 60 |     status_t    tryLock(); | 
 | 61 |  | 
| Elliott Hughes | 9b828ad | 2015-07-30 08:47:35 -0700 | [diff] [blame] | 62 | #if defined(__ANDROID__) | 
| Jesse Hall | 601424a | 2014-12-23 14:00:29 -0800 | [diff] [blame] | 63 |     // lock the mutex, but don't wait longer than timeoutMilliseconds. | 
 | 64 |     // Returns 0 on success, TIMED_OUT for failure due to timeout expiration. | 
 | 65 |     // | 
 | 66 |     // OSX doesn't have pthread_mutex_timedlock() or equivalent. To keep | 
 | 67 |     // capabilities consistent across host OSes, this method is only available | 
 | 68 |     // when building Android binaries. | 
 | 69 |     status_t    timedLock(nsecs_t timeoutMilliseconds); | 
 | 70 | #endif | 
 | 71 |  | 
| Mathias Agopian | 2bd9959 | 2012-02-25 23:02:14 -0800 | [diff] [blame] | 72 |     // Manages the mutex automatically. It'll be locked when Autolock is | 
 | 73 |     // constructed and released when Autolock goes out of scope. | 
 | 74 |     class Autolock { | 
 | 75 |     public: | 
 | 76 |         inline Autolock(Mutex& mutex) : mLock(mutex)  { mLock.lock(); } | 
 | 77 |         inline Autolock(Mutex* mutex) : mLock(*mutex) { mLock.lock(); } | 
 | 78 |         inline ~Autolock() { mLock.unlock(); } | 
 | 79 |     private: | 
 | 80 |         Mutex& mLock; | 
 | 81 |     }; | 
 | 82 |  | 
 | 83 | private: | 
 | 84 |     friend class Condition; | 
| Jesse Hall | 601424a | 2014-12-23 14:00:29 -0800 | [diff] [blame] | 85 |  | 
| Mathias Agopian | 2bd9959 | 2012-02-25 23:02:14 -0800 | [diff] [blame] | 86 |     // A mutex cannot be copied | 
 | 87 |                 Mutex(const Mutex&); | 
 | 88 |     Mutex&      operator = (const Mutex&); | 
| Jesse Hall | 601424a | 2014-12-23 14:00:29 -0800 | [diff] [blame] | 89 |  | 
| Yabin Cui | 4a6e5a3 | 2015-01-26 19:48:54 -0800 | [diff] [blame] | 90 | #if !defined(_WIN32) | 
| Mathias Agopian | 2bd9959 | 2012-02-25 23:02:14 -0800 | [diff] [blame] | 91 |     pthread_mutex_t mMutex; | 
 | 92 | #else | 
 | 93 |     void    _init(); | 
 | 94 |     void*   mState; | 
 | 95 | #endif | 
 | 96 | }; | 
 | 97 |  | 
 | 98 | // --------------------------------------------------------------------------- | 
 | 99 |  | 
| Yabin Cui | 4a6e5a3 | 2015-01-26 19:48:54 -0800 | [diff] [blame] | 100 | #if !defined(_WIN32) | 
| Mathias Agopian | 2bd9959 | 2012-02-25 23:02:14 -0800 | [diff] [blame] | 101 |  | 
 | 102 | inline Mutex::Mutex() { | 
 | 103 |     pthread_mutex_init(&mMutex, NULL); | 
 | 104 | } | 
| Igor Murashkin | a27c1e0 | 2012-12-05 16:10:26 -0800 | [diff] [blame] | 105 | inline Mutex::Mutex(__attribute__((unused)) const char* name) { | 
| Mathias Agopian | 2bd9959 | 2012-02-25 23:02:14 -0800 | [diff] [blame] | 106 |     pthread_mutex_init(&mMutex, NULL); | 
 | 107 | } | 
| Igor Murashkin | a27c1e0 | 2012-12-05 16:10:26 -0800 | [diff] [blame] | 108 | inline Mutex::Mutex(int type, __attribute__((unused)) const char* name) { | 
| Mathias Agopian | 2bd9959 | 2012-02-25 23:02:14 -0800 | [diff] [blame] | 109 |     if (type == SHARED) { | 
 | 110 |         pthread_mutexattr_t attr; | 
 | 111 |         pthread_mutexattr_init(&attr); | 
 | 112 |         pthread_mutexattr_setpshared(&attr, PTHREAD_PROCESS_SHARED); | 
 | 113 |         pthread_mutex_init(&mMutex, &attr); | 
 | 114 |         pthread_mutexattr_destroy(&attr); | 
 | 115 |     } else { | 
 | 116 |         pthread_mutex_init(&mMutex, NULL); | 
 | 117 |     } | 
 | 118 | } | 
 | 119 | inline Mutex::~Mutex() { | 
 | 120 |     pthread_mutex_destroy(&mMutex); | 
 | 121 | } | 
 | 122 | inline status_t Mutex::lock() { | 
 | 123 |     return -pthread_mutex_lock(&mMutex); | 
 | 124 | } | 
 | 125 | inline void Mutex::unlock() { | 
 | 126 |     pthread_mutex_unlock(&mMutex); | 
 | 127 | } | 
 | 128 | inline status_t Mutex::tryLock() { | 
 | 129 |     return -pthread_mutex_trylock(&mMutex); | 
 | 130 | } | 
| Elliott Hughes | 9b828ad | 2015-07-30 08:47:35 -0700 | [diff] [blame] | 131 | #if defined(__ANDROID__) | 
| Jesse Hall | 601424a | 2014-12-23 14:00:29 -0800 | [diff] [blame] | 132 | inline status_t Mutex::timedLock(nsecs_t timeoutNs) { | 
 | 133 |     const struct timespec ts = { | 
| Chih-Hung Hsieh | ba8cdf9 | 2015-01-12 16:21:46 -0800 | [diff] [blame] | 134 |         /* .tv_sec = */ static_cast<time_t>(timeoutNs / 1000000000), | 
 | 135 |         /* .tv_nsec = */ static_cast<long>(timeoutNs % 1000000000), | 
| Jesse Hall | 601424a | 2014-12-23 14:00:29 -0800 | [diff] [blame] | 136 |     }; | 
 | 137 |     return -pthread_mutex_timedlock(&mMutex, &ts); | 
 | 138 | } | 
 | 139 | #endif | 
| Mathias Agopian | 2bd9959 | 2012-02-25 23:02:14 -0800 | [diff] [blame] | 140 |  | 
| Yabin Cui | 4a6e5a3 | 2015-01-26 19:48:54 -0800 | [diff] [blame] | 141 | #endif // !defined(_WIN32) | 
| Mathias Agopian | 2bd9959 | 2012-02-25 23:02:14 -0800 | [diff] [blame] | 142 |  | 
 | 143 | // --------------------------------------------------------------------------- | 
 | 144 |  | 
 | 145 | /* | 
 | 146 |  * Automatic mutex.  Declare one of these at the top of a function. | 
 | 147 |  * When the function returns, it will go out of scope, and release the | 
 | 148 |  * mutex. | 
 | 149 |  */ | 
| Jesse Hall | 601424a | 2014-12-23 14:00:29 -0800 | [diff] [blame] | 150 |  | 
| Mathias Agopian | 2bd9959 | 2012-02-25 23:02:14 -0800 | [diff] [blame] | 151 | typedef Mutex::Autolock AutoMutex; | 
 | 152 |  | 
 | 153 | // --------------------------------------------------------------------------- | 
 | 154 | }; // namespace android | 
 | 155 | // --------------------------------------------------------------------------- | 
 | 156 |  | 
 | 157 | #endif // _LIBS_UTILS_MUTEX_H |