diff options
| author | Vijay Venkatraman <vijaykv@google.com> | 2017-01-26 02:03:45 +0000 |
|---|---|---|
| committer | android-build-merger <android-build-merger@google.com> | 2017-01-26 02:03:45 +0000 |
| commit | a040114bcba4b202a289a6e8fafd808f779f865c (patch) | |
| tree | dadf435a27ba8b3ac32996e39af86a6353c67396 /libutils/include/utils/Condition.h | |
| parent | a867efaed83fb3dab038e3fbe0cf608407678cb0 (diff) | |
| parent | 5a8f555e493803f4bff4a402d36d11b5cd81498f (diff) | |
| download | system_core-a040114bcba4b202a289a6e8fafd808f779f865c.tar.gz system_core-a040114bcba4b202a289a6e8fafd808f779f865c.tar.bz2 system_core-a040114bcba4b202a289a6e8fafd808f779f865c.zip | |
Merge "Exporting C++ headers from system/core" am: 812b7d5d52 am: f484dd3401 am: a252f11da3
am: 5a8f555e49
Change-Id: Id449aadc3b9e6e263d351ce031b1f7f7bb4672b8
Diffstat (limited to 'libutils/include/utils/Condition.h')
| -rw-r--r-- | libutils/include/utils/Condition.h | 165 |
1 files changed, 165 insertions, 0 deletions
diff --git a/libutils/include/utils/Condition.h b/libutils/include/utils/Condition.h new file mode 100644 index 000000000..25a53aa23 --- /dev/null +++ b/libutils/include/utils/Condition.h @@ -0,0 +1,165 @@ +/* + * Copyright (C) 2007 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _LIBS_UTILS_CONDITION_H +#define _LIBS_UTILS_CONDITION_H + +#include <limits.h> +#include <stdint.h> +#include <sys/types.h> +#include <time.h> + +#if !defined(_WIN32) +# include <pthread.h> +#endif + +#include <utils/Errors.h> +#include <utils/Mutex.h> +#include <utils/Timers.h> + +// --------------------------------------------------------------------------- +namespace android { +// --------------------------------------------------------------------------- + +/* + * Condition variable class. The implementation is system-dependent. + * + * Condition variables are paired up with mutexes. Lock the mutex, + * call wait(), then either re-wait() if things aren't quite what you want, + * or unlock the mutex and continue. All threads calling wait() must + * use the same mutex for a given Condition. + */ +class Condition { +public: + enum { + PRIVATE = 0, + SHARED = 1 + }; + + enum WakeUpType { + WAKE_UP_ONE = 0, + WAKE_UP_ALL = 1 + }; + + Condition(); + explicit Condition(int type); + ~Condition(); + // Wait on the condition variable. Lock the mutex before calling. + status_t wait(Mutex& mutex); + // same with relative timeout + status_t waitRelative(Mutex& mutex, nsecs_t reltime); + // Signal the condition variable, allowing exactly one thread to continue. + void signal(); + // Signal the condition variable, allowing one or all threads to continue. + void signal(WakeUpType type) { + if (type == WAKE_UP_ONE) { + signal(); + } else { + broadcast(); + } + } + // Signal the condition variable, allowing all threads to continue. + void broadcast(); + +private: +#if !defined(_WIN32) + pthread_cond_t mCond; +#else + void* mState; +#endif +}; + +// --------------------------------------------------------------------------- + +#if !defined(_WIN32) + +inline Condition::Condition() { + pthread_cond_init(&mCond, NULL); +} +inline Condition::Condition(int type) { + if (type == SHARED) { + pthread_condattr_t attr; + pthread_condattr_init(&attr); + pthread_condattr_setpshared(&attr, PTHREAD_PROCESS_SHARED); + pthread_cond_init(&mCond, &attr); + pthread_condattr_destroy(&attr); + } else { + pthread_cond_init(&mCond, NULL); + } +} +inline Condition::~Condition() { + pthread_cond_destroy(&mCond); +} +inline status_t Condition::wait(Mutex& mutex) { + return -pthread_cond_wait(&mCond, &mutex.mMutex); +} +inline status_t Condition::waitRelative(Mutex& mutex, nsecs_t reltime) { + struct timespec ts; +#if defined(__linux__) + clock_gettime(CLOCK_REALTIME, &ts); +#else // __APPLE__ + // Apple doesn't support POSIX clocks. + struct timeval t; + gettimeofday(&t, NULL); + ts.tv_sec = t.tv_sec; + ts.tv_nsec = t.tv_usec*1000; +#endif + + // On 32-bit devices, tv_sec is 32-bit, but `reltime` is 64-bit. + int64_t reltime_sec = reltime/1000000000; + + ts.tv_nsec += static_cast<long>(reltime%1000000000); + if (reltime_sec < INT64_MAX && ts.tv_nsec >= 1000000000) { + ts.tv_nsec -= 1000000000; + ++reltime_sec; + } + + int64_t time_sec = ts.tv_sec; + if (time_sec > INT64_MAX - reltime_sec) { + time_sec = INT64_MAX; + } else { + time_sec += reltime_sec; + } + + ts.tv_sec = (time_sec > LONG_MAX) ? LONG_MAX : static_cast<long>(time_sec); + + return -pthread_cond_timedwait(&mCond, &mutex.mMutex, &ts); +} +inline void Condition::signal() { + /* + * POSIX says pthread_cond_signal wakes up "one or more" waiting threads. + * However bionic follows the glibc guarantee which wakes up "exactly one" + * waiting thread. + * + * man 3 pthread_cond_signal + * pthread_cond_signal restarts one of the threads that are waiting on + * the condition variable cond. If no threads are waiting on cond, + * nothing happens. If several threads are waiting on cond, exactly one + * is restarted, but it is not specified which. + */ + pthread_cond_signal(&mCond); +} +inline void Condition::broadcast() { + pthread_cond_broadcast(&mCond); +} + +#endif // !defined(_WIN32) + +// --------------------------------------------------------------------------- +}; // namespace android +// --------------------------------------------------------------------------- + +#endif // _LIBS_UTILS_CONDITON_H |
