Condition.h revision 2bd99599bb9eef197e6d1ccacb9f808ebfbcc598
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_CONDITION_H
182bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian#define _LIBS_UTILS_CONDITION_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#include <utils/Mutex.h>
302bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian#include <utils/Timers.h>
312bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian
322bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian// ---------------------------------------------------------------------------
332bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopiannamespace android {
342bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian// ---------------------------------------------------------------------------
352bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian
362bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian/*
372bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian * Condition variable class.  The implementation is system-dependent.
382bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian *
392bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian * Condition variables are paired up with mutexes.  Lock the mutex,
402bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian * call wait(), then either re-wait() if things aren't quite what you want,
412bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian * or unlock the mutex and continue.  All threads calling wait() must
422bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian * use the same mutex for a given Condition.
432bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian */
442bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopianclass Condition {
452bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopianpublic:
462bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian    enum {
472bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian        PRIVATE = 0,
482bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian        SHARED = 1
492bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian    };
502bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian
512bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian    Condition();
522bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian    Condition(int type);
532bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian    ~Condition();
542bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian    // Wait on the condition variable.  Lock the mutex before calling.
552bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian    status_t wait(Mutex& mutex);
562bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian    // same with relative timeout
572bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian    status_t waitRelative(Mutex& mutex, nsecs_t reltime);
582bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian    // Signal the condition variable, allowing one thread to continue.
592bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian    void signal();
602bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian    // Signal the condition variable, allowing all threads to continue.
612bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian    void broadcast();
622bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian
632bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopianprivate:
642bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian#if defined(HAVE_PTHREADS)
652bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian    pthread_cond_t mCond;
662bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian#else
672bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian    void*   mState;
682bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian#endif
692bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian};
702bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian
712bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian// ---------------------------------------------------------------------------
722bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian
732bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian#if defined(HAVE_PTHREADS)
742bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian
752bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopianinline Condition::Condition() {
762bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian    pthread_cond_init(&mCond, NULL);
772bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian}
782bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopianinline Condition::Condition(int type) {
792bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian    if (type == SHARED) {
802bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian        pthread_condattr_t attr;
812bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian        pthread_condattr_init(&attr);
822bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian        pthread_condattr_setpshared(&attr, PTHREAD_PROCESS_SHARED);
832bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian        pthread_cond_init(&mCond, &attr);
842bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian        pthread_condattr_destroy(&attr);
852bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian    } else {
862bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian        pthread_cond_init(&mCond, NULL);
872bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian    }
882bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian}
892bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopianinline Condition::~Condition() {
902bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian    pthread_cond_destroy(&mCond);
912bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian}
922bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopianinline status_t Condition::wait(Mutex& mutex) {
932bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian    return -pthread_cond_wait(&mCond, &mutex.mMutex);
942bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian}
952bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopianinline status_t Condition::waitRelative(Mutex& mutex, nsecs_t reltime) {
962bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian#if defined(HAVE_PTHREAD_COND_TIMEDWAIT_RELATIVE)
972bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian    struct timespec ts;
982bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian    ts.tv_sec  = reltime/1000000000;
992bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian    ts.tv_nsec = reltime%1000000000;
1002bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian    return -pthread_cond_timedwait_relative_np(&mCond, &mutex.mMutex, &ts);
1012bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian#else // HAVE_PTHREAD_COND_TIMEDWAIT_RELATIVE
1022bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian    struct timespec ts;
1032bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian#if defined(HAVE_POSIX_CLOCKS)
1042bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian    clock_gettime(CLOCK_REALTIME, &ts);
1052bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian#else // HAVE_POSIX_CLOCKS
1062bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian    // we don't support the clocks here.
1072bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian    struct timeval t;
1082bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian    gettimeofday(&t, NULL);
1092bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian    ts.tv_sec = t.tv_sec;
1102bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian    ts.tv_nsec= t.tv_usec*1000;
1112bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian#endif // HAVE_POSIX_CLOCKS
1122bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian    ts.tv_sec += reltime/1000000000;
1132bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian    ts.tv_nsec+= reltime%1000000000;
1142bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian    if (ts.tv_nsec >= 1000000000) {
1152bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian        ts.tv_nsec -= 1000000000;
1162bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian        ts.tv_sec  += 1;
1172bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian    }
1182bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian    return -pthread_cond_timedwait(&mCond, &mutex.mMutex, &ts);
1192bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian#endif // HAVE_PTHREAD_COND_TIMEDWAIT_RELATIVE
1202bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian}
1212bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopianinline void Condition::signal() {
1222bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian    pthread_cond_signal(&mCond);
1232bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian}
1242bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopianinline void Condition::broadcast() {
1252bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian    pthread_cond_broadcast(&mCond);
1262bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian}
1272bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian
1282bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian#endif // HAVE_PTHREADS
1292bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian
1302bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian// ---------------------------------------------------------------------------
1312bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian}; // namespace android
1322bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian// ---------------------------------------------------------------------------
1332bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian
1342bd99599bb9eef197e6d1ccacb9f808ebfbcc598Mathias Agopian#endif // _LIBS_UTILS_CONDITON_H
135