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(HAVE_PTHREADS)
25# include <pthread.h>
26#endif
27
28#include <utils/Errors.h>
29
30// ---------------------------------------------------------------------------
31namespace android {
32// ---------------------------------------------------------------------------
33
34class Condition;
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 */
42class Mutex {
43public:
44    enum {
45        PRIVATE = 0,
46        SHARED = 1
47    };
48
49                Mutex();
50                Mutex(const char* name);
51                Mutex(int type, const char* name = NULL);
52                ~Mutex();
53
54    // lock or unlock the mutex
55    status_t    lock();
56    void        unlock();
57
58    // lock if possible; returns 0 on success, error otherwise
59    status_t    tryLock();
60
61    // Manages the mutex automatically. It'll be locked when Autolock is
62    // constructed and released when Autolock goes out of scope.
63    class Autolock {
64    public:
65        inline Autolock(Mutex& mutex) : mLock(mutex)  { mLock.lock(); }
66        inline Autolock(Mutex* mutex) : mLock(*mutex) { mLock.lock(); }
67        inline ~Autolock() { mLock.unlock(); }
68    private:
69        Mutex& mLock;
70    };
71
72private:
73    friend class Condition;
74
75    // A mutex cannot be copied
76                Mutex(const Mutex&);
77    Mutex&      operator = (const Mutex&);
78
79#if defined(HAVE_PTHREADS)
80    pthread_mutex_t mMutex;
81#else
82    void    _init();
83    void*   mState;
84#endif
85};
86
87// ---------------------------------------------------------------------------
88
89#if defined(HAVE_PTHREADS)
90
91inline Mutex::Mutex() {
92    pthread_mutex_init(&mMutex, NULL);
93}
94inline Mutex::Mutex(const char* name) {
95    pthread_mutex_init(&mMutex, NULL);
96}
97inline Mutex::Mutex(int type, const char* name) {
98    if (type == SHARED) {
99        pthread_mutexattr_t attr;
100        pthread_mutexattr_init(&attr);
101        pthread_mutexattr_setpshared(&attr, PTHREAD_PROCESS_SHARED);
102        pthread_mutex_init(&mMutex, &attr);
103        pthread_mutexattr_destroy(&attr);
104    } else {
105        pthread_mutex_init(&mMutex, NULL);
106    }
107}
108inline Mutex::~Mutex() {
109    pthread_mutex_destroy(&mMutex);
110}
111inline status_t Mutex::lock() {
112    return -pthread_mutex_lock(&mMutex);
113}
114inline void Mutex::unlock() {
115    pthread_mutex_unlock(&mMutex);
116}
117inline status_t Mutex::tryLock() {
118    return -pthread_mutex_trylock(&mMutex);
119}
120
121#endif // HAVE_PTHREADS
122
123// ---------------------------------------------------------------------------
124
125/*
126 * Automatic mutex.  Declare one of these at the top of a function.
127 * When the function returns, it will go out of scope, and release the
128 * mutex.
129 */
130
131typedef Mutex::Autolock AutoMutex;
132
133// ---------------------------------------------------------------------------
134}; // namespace android
135// ---------------------------------------------------------------------------
136
137#endif // _LIBS_UTILS_MUTEX_H
138