12bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian/*
22bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian * Copyright (C) 2007 The Android Open Source Project
32bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian *
42bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian * Licensed under the Apache License, Version 2.0 (the "License");
52bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian * you may not use this file except in compliance with the License.
62bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian * You may obtain a copy of the License at
72bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian *
82bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian *      http://www.apache.org/licenses/LICENSE-2.0
92bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian *
102bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian * Unless required by applicable law or agreed to in writing, software
112bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian * distributed under the License is distributed on an "AS IS" BASIS,
122bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
132bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian * See the License for the specific language governing permissions and
142bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian * limitations under the License.
152bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian */
162bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian
172bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian#ifndef _LIBS_UTILS_MUTEX_H
182bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian#define _LIBS_UTILS_MUTEX_H
192bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian
202bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian#include <stdint.h>
212bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian#include <sys/types.h>
222bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian#include <time.h>
232bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian
242bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian#if defined(HAVE_PTHREADS)
252bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian# include <pthread.h>
262bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian#endif
272bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian
282bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian#include <utils/Errors.h>
292bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian
302bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian// ---------------------------------------------------------------------------
312bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopiannamespace android {
322bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian// ---------------------------------------------------------------------------
332bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian
342bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopianclass Condition;
352bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian
362bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian/*
372bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian * Simple mutex class.  The implementation is system-dependent.
382bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian *
392bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian * The mutex must be unlocked by the thread that locked it.  They are not
402bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian * recursive, i.e. the same thread can't lock it multiple times.
412bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian */
422bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopianclass Mutex {
432bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopianpublic:
442bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian    enum {
452bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian        PRIVATE = 0,
462bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian        SHARED = 1
472bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian    };
482bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian
492bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian                Mutex();
502bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian                Mutex(const char* name);
512bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian                Mutex(int type, const char* name = NULL);
522bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian                ~Mutex();
532bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian
542bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian    // lock or unlock the mutex
552bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian    status_t    lock();
562bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian    void        unlock();
572bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian
582bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian    // lock if possible; returns 0 on success, error otherwise
592bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian    status_t    tryLock();
602bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian
612bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian    // Manages the mutex automatically. It'll be locked when Autolock is
622bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian    // constructed and released when Autolock goes out of scope.
632bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian    class Autolock {
642bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian    public:
652bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian        inline Autolock(Mutex& mutex) : mLock(mutex)  { mLock.lock(); }
662bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian        inline Autolock(Mutex* mutex) : mLock(*mutex) { mLock.lock(); }
672bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian        inline ~Autolock() { mLock.unlock(); }
682bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian    private:
692bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian        Mutex& mLock;
702bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian    };
712bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian
722bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopianprivate:
732bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian    friend class Condition;
742bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian
752bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian    // A mutex cannot be copied
762bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian                Mutex(const Mutex&);
772bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian    Mutex&      operator = (const Mutex&);
782bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian
792bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian#if defined(HAVE_PTHREADS)
802bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian    pthread_mutex_t mMutex;
812bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian#else
822bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian    void    _init();
832bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian    void*   mState;
842bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian#endif
852bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian};
862bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian
872bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian// ---------------------------------------------------------------------------
882bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian
892bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian#if defined(HAVE_PTHREADS)
902bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian
912bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopianinline Mutex::Mutex() {
922bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian    pthread_mutex_init(&mMutex, NULL);
932bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian}
94a27c1e08396aa2969511dad1f661d10c2b835ac1Igor Murashkininline Mutex::Mutex(__attribute__((unused)) const char* name) {
952bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian    pthread_mutex_init(&mMutex, NULL);
962bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian}
97a27c1e08396aa2969511dad1f661d10c2b835ac1Igor Murashkininline Mutex::Mutex(int type, __attribute__((unused)) const char* name) {
982bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian    if (type == SHARED) {
992bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian        pthread_mutexattr_t attr;
1002bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian        pthread_mutexattr_init(&attr);
1012bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian        pthread_mutexattr_setpshared(&attr, PTHREAD_PROCESS_SHARED);
1022bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian        pthread_mutex_init(&mMutex, &attr);
1032bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian        pthread_mutexattr_destroy(&attr);
1042bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian    } else {
1052bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian        pthread_mutex_init(&mMutex, NULL);
1062bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian    }
1072bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian}
1082bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopianinline Mutex::~Mutex() {
1092bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian    pthread_mutex_destroy(&mMutex);
1102bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian}
1112bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopianinline status_t Mutex::lock() {
1122bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian    return -pthread_mutex_lock(&mMutex);
1132bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian}
1142bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopianinline void Mutex::unlock() {
1152bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian    pthread_mutex_unlock(&mMutex);
1162bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian}
1172bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopianinline status_t Mutex::tryLock() {
1182bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian    return -pthread_mutex_trylock(&mMutex);
1192bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian}
1202bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian
1212bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian#endif // HAVE_PTHREADS
1222bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian
1232bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian// ---------------------------------------------------------------------------
1242bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian
1252bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian/*
1262bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian * Automatic mutex.  Declare one of these at the top of a function.
1272bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian * When the function returns, it will go out of scope, and release the
1282bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian * mutex.
1292bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian */
1302bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian
1312bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopiantypedef Mutex::Autolock AutoMutex;
1322bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian
1332bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian// ---------------------------------------------------------------------------
1342bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian}; // namespace android
1352bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian// ---------------------------------------------------------------------------
1362bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian
1372bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian#endif // _LIBS_UTILS_MUTEX_H
138