summaryrefslogtreecommitdiffstats
path: root/chrome/browser/sync/util/pthread_helpers.h
diff options
context:
space:
mode:
Diffstat (limited to 'chrome/browser/sync/util/pthread_helpers.h')
-rw-r--r--chrome/browser/sync/util/pthread_helpers.h259
1 files changed, 259 insertions, 0 deletions
diff --git a/chrome/browser/sync/util/pthread_helpers.h b/chrome/browser/sync/util/pthread_helpers.h
new file mode 100644
index 0000000..26defe0
--- /dev/null
+++ b/chrome/browser/sync/util/pthread_helpers.h
@@ -0,0 +1,259 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_SYNC_UTIL_PTHREAD_HELPERS_H_
+#define CHROME_BROWSER_SYNC_UTIL_PTHREAD_HELPERS_H_
+
+#include <pthread.h>
+#include "base/logging.h"
+
+#ifdef OS_WINDOWS
+typedef void* thread_handle;
+#else
+typedef pthread_t thread_handle;
+#endif
+
+// Creates a pthread, detaches from it, and returns a Win32 HANDLE for it that
+// the caller must CloseHandle().
+thread_handle CreatePThread(void* (*start)(void* payload), void* parameter);
+
+class PThreadRWLock {
+ public:
+ inline PThreadRWLock() {
+ int result = pthread_rwlock_init(&rwlock_, 0);
+ DCHECK_EQ(0, result);
+ }
+ ~PThreadRWLock() {
+ int result = pthread_rwlock_destroy(&rwlock_);
+ DCHECK_EQ(0, result);
+ }
+ pthread_rwlock_t rwlock_;
+
+ DISALLOW_COPY_AND_ASSIGN(PThreadRWLock);
+};
+
+// ScopedReadLock attempts to acquire a write lock in its constructor and then
+// releases it in its destructor.
+class ScopedWriteLock {
+ public:
+ explicit ScopedWriteLock(pthread_rwlock_t* rwlock) : rwlock_(rwlock) {
+ int result = pthread_rwlock_wrlock(rwlock_);
+ DCHECK_EQ(0, result);
+ }
+
+ explicit ScopedWriteLock(PThreadRWLock* rwlock) : rwlock_(&rwlock->rwlock_) {
+ int result = pthread_rwlock_wrlock(rwlock_);
+ DCHECK_EQ(0, result);
+ }
+
+ ~ScopedWriteLock() {
+ int result = pthread_rwlock_unlock(rwlock_);
+ DCHECK_EQ(0, result);
+ }
+
+ protected:
+ pthread_rwlock_t* rwlock_;
+ private:
+ DISALLOW_COPY_AND_ASSIGN(ScopedWriteLock);
+};
+
+// ScopedReadLock attempts to acquire a read lock in its constructor and then
+// releases it in its destructor.
+class ScopedReadLock {
+ public:
+ explicit ScopedReadLock(pthread_rwlock_t* rwlock) : rwlock_(rwlock) {
+ int result = pthread_rwlock_rdlock(rwlock_);
+ DCHECK_EQ(0, result);
+ }
+
+ explicit ScopedReadLock(PThreadRWLock* rwlock) : rwlock_(&rwlock->rwlock_) {
+ int result = pthread_rwlock_rdlock(rwlock_);
+ DCHECK_EQ(0, result);
+ }
+
+ ~ScopedReadLock() {
+ int result = pthread_rwlock_unlock(rwlock_);
+ DCHECK_EQ(0, result);
+ }
+ protected:
+ pthread_rwlock_t* rwlock_;
+ private:
+ DISALLOW_COPY_AND_ASSIGN(ScopedReadLock);
+};
+
+template <typename LockType>
+class PThreadScopedLock {
+ public:
+ explicit inline PThreadScopedLock(LockType* lock) : lock_(lock) {
+ if (lock_)
+ lock->Lock();
+ }
+ inline ~PThreadScopedLock() {
+ Unlock();
+ }
+ inline void Unlock() {
+ if (lock_) {
+ lock_->Unlock();
+ lock_ = NULL;
+ }
+ }
+ LockType* lock_;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(PThreadScopedLock);
+};
+
+class PThreadNoLock {
+ public:
+ inline void Lock() { }
+ inline void Unlock() { }
+};
+
+// On win32, the pthread mutex implementation is about as efficient a critical
+// section. It uses atomic operations and only needs kernel calls on
+// contention.
+class PThreadMutex {
+ public:
+ inline PThreadMutex() {
+ pthread_mutexattr_t* attributes = NULL;
+#ifndef NDEBUG
+ private_attributes_in_use_ = true;
+ pthread_mutexattr_init(&mutex_attributes_);
+ pthread_mutexattr_settype(&mutex_attributes_, PTHREAD_MUTEX_ERRORCHECK);
+ attributes = &mutex_attributes_;
+#endif
+ int result = pthread_mutex_init(&mutex_, attributes);
+ DCHECK_EQ(0, result);
+ }
+ inline explicit PThreadMutex(const pthread_mutexattr_t* attr) {
+#ifndef NDEBUG
+ private_attributes_in_use_ = false;
+#endif
+ int result = pthread_mutex_init(&mutex_, attr);
+ DCHECK_EQ(0, result);
+ }
+ inline ~PThreadMutex() {
+ int result = pthread_mutex_destroy(&mutex_);
+ DCHECK_EQ(0, result);
+#ifndef NDEBUG
+ if (private_attributes_in_use_) {
+ pthread_mutexattr_destroy(&mutex_attributes_);
+ }
+#endif
+ }
+ inline void Lock() {
+ int result = pthread_mutex_lock(&mutex_);
+ DCHECK_EQ(0, result);
+ }
+ inline void Unlock() {
+ int result = pthread_mutex_unlock(&mutex_);
+ DCHECK_EQ(0, result);
+ }
+ pthread_mutex_t mutex_;
+
+#ifndef NDEBUG
+ pthread_mutexattr_t mutex_attributes_;
+ bool private_attributes_in_use_;
+#endif
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(PThreadMutex);
+};
+
+class PThreadMutexAttr {
+ public:
+ pthread_mutexattr_t attr;
+ inline PThreadMutexAttr(int type) {
+ pthread_mutexattr_init(&attr);
+ pthread_mutexattr_settype(&attr, type);
+ }
+ inline ~PThreadMutexAttr() {
+ pthread_mutexattr_destroy(&attr);
+ }
+ private:
+ DISALLOW_COPY_AND_ASSIGN(PThreadMutexAttr);
+};
+
+class PThreadRecursiveMutex : public PThreadMutex {
+ public:
+ inline PThreadRecursiveMutex() : PThreadMutex(recursive_attr()) {}
+ private:
+ static inline pthread_mutexattr_t* recursive_attr() {
+ static PThreadMutexAttr recursive(PTHREAD_MUTEX_RECURSIVE);
+ return &recursive.attr;
+ }
+ DISALLOW_COPY_AND_ASSIGN(PThreadRecursiveMutex);
+};
+
+
+class PThreadScopedDisabledCancellation {
+ public:
+ inline PThreadScopedDisabledCancellation() {
+ pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &old_cancel_state_);
+ }
+ inline ~PThreadScopedDisabledCancellation() {
+ pthread_setcancelstate(old_cancel_state_, NULL);
+ }
+ private:
+ int old_cancel_state_;
+
+ DISALLOW_COPY_AND_ASSIGN(PThreadScopedDisabledCancellation);
+};
+
+class PThreadCondVar {
+ public:
+ inline PThreadCondVar() {
+ int result = pthread_cond_init(&condvar_, 0);
+ DCHECK_EQ(0, result);
+ }
+ ~PThreadCondVar() {
+ int result = pthread_cond_destroy(&condvar_);
+ DCHECK_EQ(0, result);
+ }
+ inline void Signal() {
+ int result = pthread_cond_signal(&condvar_);
+ DCHECK_EQ(0, result);
+ }
+ inline void Broadcast() {
+ int result = pthread_cond_broadcast(&condvar_);
+ DCHECK_EQ(0, result);
+ }
+ pthread_cond_t condvar_;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(PThreadCondVar);
+};
+
+template <typename ValueType>
+class PThreadThreadVar {
+ public:
+ PThreadThreadVar(void (*destructor)(void* payload)) {
+ int result = pthread_key_create(&thread_key_, destructor);
+ DCHECK_EQ(0, result);
+ }
+ ~PThreadThreadVar() {
+ int result = pthread_key_delete(thread_key_);
+ DCHECK_EQ(0, result);
+ }
+ void SetValue(ValueType value) {
+ int result = pthread_setspecific(thread_key_, static_cast<void*>(value));
+ DCHECK_EQ(0, result);
+ }
+ ValueType GetValue() {
+ return static_cast<ValueType>(pthread_getspecific(thread_key_));
+ }
+ private:
+ pthread_key_t thread_key_;
+ DISALLOW_COPY_AND_ASSIGN(PThreadThreadVar);
+};
+
+// Returns the absolute time ms milliseconds from now. Useful for passing
+// result to pthread_cond_timedwait().
+struct timespec GetPThreadAbsoluteTime(uint32 ms_from_now);
+
+// Assign a descriptive label to the current thread. This is useful to see
+// in a GUI debugger, but may not be implementable on all platforms.
+void NameCurrentThreadForDebugging(char* name);
+
+#endif // CHROME_BROWSER_SYNC_UTIL_PTHREAD_HELPERS_H_