OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #ifndef CHROME_BROWSER_SYNC_UTIL_PTHREAD_HELPERS_H_ |
| 6 #define CHROME_BROWSER_SYNC_UTIL_PTHREAD_HELPERS_H_ |
| 7 |
| 8 #include <pthread.h> |
| 9 #include "base/logging.h" |
| 10 |
| 11 #ifdef OS_WINDOWS |
| 12 typedef void* thread_handle; |
| 13 #else |
| 14 typedef pthread_t thread_handle; |
| 15 #endif |
| 16 |
| 17 // Creates a pthread, detaches from it, and returns a Win32 HANDLE for it that |
| 18 // the caller must CloseHandle(). |
| 19 thread_handle CreatePThread(void* (*start)(void* payload), void* parameter); |
| 20 |
| 21 class PThreadRWLock { |
| 22 public: |
| 23 inline PThreadRWLock() { |
| 24 int result = pthread_rwlock_init(&rwlock_, 0); |
| 25 DCHECK_EQ(0, result); |
| 26 } |
| 27 ~PThreadRWLock() { |
| 28 int result = pthread_rwlock_destroy(&rwlock_); |
| 29 DCHECK_EQ(0, result); |
| 30 } |
| 31 pthread_rwlock_t rwlock_; |
| 32 |
| 33 DISALLOW_COPY_AND_ASSIGN(PThreadRWLock); |
| 34 }; |
| 35 |
| 36 // ScopedReadLock attempts to acquire a write lock in its constructor and then |
| 37 // releases it in its destructor. |
| 38 class ScopedWriteLock { |
| 39 public: |
| 40 explicit ScopedWriteLock(pthread_rwlock_t* rwlock) : rwlock_(rwlock) { |
| 41 int result = pthread_rwlock_wrlock(rwlock_); |
| 42 DCHECK_EQ(0, result); |
| 43 } |
| 44 |
| 45 explicit ScopedWriteLock(PThreadRWLock* rwlock) : rwlock_(&rwlock->rwlock_) { |
| 46 int result = pthread_rwlock_wrlock(rwlock_); |
| 47 DCHECK_EQ(0, result); |
| 48 } |
| 49 |
| 50 ~ScopedWriteLock() { |
| 51 int result = pthread_rwlock_unlock(rwlock_); |
| 52 DCHECK_EQ(0, result); |
| 53 } |
| 54 |
| 55 protected: |
| 56 pthread_rwlock_t* rwlock_; |
| 57 private: |
| 58 DISALLOW_COPY_AND_ASSIGN(ScopedWriteLock); |
| 59 }; |
| 60 |
| 61 // ScopedReadLock attempts to acquire a read lock in its constructor and then |
| 62 // releases it in its destructor. |
| 63 class ScopedReadLock { |
| 64 public: |
| 65 explicit ScopedReadLock(pthread_rwlock_t* rwlock) : rwlock_(rwlock) { |
| 66 int result = pthread_rwlock_rdlock(rwlock_); |
| 67 DCHECK_EQ(0, result); |
| 68 } |
| 69 |
| 70 explicit ScopedReadLock(PThreadRWLock* rwlock) : rwlock_(&rwlock->rwlock_) { |
| 71 int result = pthread_rwlock_rdlock(rwlock_); |
| 72 DCHECK_EQ(0, result); |
| 73 } |
| 74 |
| 75 ~ScopedReadLock() { |
| 76 int result = pthread_rwlock_unlock(rwlock_); |
| 77 DCHECK_EQ(0, result); |
| 78 } |
| 79 protected: |
| 80 pthread_rwlock_t* rwlock_; |
| 81 private: |
| 82 DISALLOW_COPY_AND_ASSIGN(ScopedReadLock); |
| 83 }; |
| 84 |
| 85 template <typename LockType> |
| 86 class PThreadScopedLock { |
| 87 public: |
| 88 explicit inline PThreadScopedLock(LockType* lock) : lock_(lock) { |
| 89 if (lock_) |
| 90 lock->Lock(); |
| 91 } |
| 92 inline ~PThreadScopedLock() { |
| 93 Unlock(); |
| 94 } |
| 95 inline void Unlock() { |
| 96 if (lock_) { |
| 97 lock_->Unlock(); |
| 98 lock_ = NULL; |
| 99 } |
| 100 } |
| 101 LockType* lock_; |
| 102 |
| 103 private: |
| 104 DISALLOW_COPY_AND_ASSIGN(PThreadScopedLock); |
| 105 }; |
| 106 |
| 107 class PThreadNoLock { |
| 108 public: |
| 109 inline void Lock() { } |
| 110 inline void Unlock() { } |
| 111 }; |
| 112 |
| 113 // On win32, the pthread mutex implementation is about as efficient a critical |
| 114 // section. It uses atomic operations and only needs kernel calls on |
| 115 // contention. |
| 116 class PThreadMutex { |
| 117 public: |
| 118 inline PThreadMutex() { |
| 119 pthread_mutexattr_t* attributes = NULL; |
| 120 #ifndef NDEBUG |
| 121 private_attributes_in_use_ = true; |
| 122 pthread_mutexattr_init(&mutex_attributes_); |
| 123 pthread_mutexattr_settype(&mutex_attributes_, PTHREAD_MUTEX_ERRORCHECK); |
| 124 attributes = &mutex_attributes_; |
| 125 #endif |
| 126 int result = pthread_mutex_init(&mutex_, attributes); |
| 127 DCHECK_EQ(0, result); |
| 128 } |
| 129 inline explicit PThreadMutex(const pthread_mutexattr_t* attr) { |
| 130 #ifndef NDEBUG |
| 131 private_attributes_in_use_ = false; |
| 132 #endif |
| 133 int result = pthread_mutex_init(&mutex_, attr); |
| 134 DCHECK_EQ(0, result); |
| 135 } |
| 136 inline ~PThreadMutex() { |
| 137 int result = pthread_mutex_destroy(&mutex_); |
| 138 DCHECK_EQ(0, result); |
| 139 #ifndef NDEBUG |
| 140 if (private_attributes_in_use_) { |
| 141 pthread_mutexattr_destroy(&mutex_attributes_); |
| 142 } |
| 143 #endif |
| 144 } |
| 145 inline void Lock() { |
| 146 int result = pthread_mutex_lock(&mutex_); |
| 147 DCHECK_EQ(0, result); |
| 148 } |
| 149 inline void Unlock() { |
| 150 int result = pthread_mutex_unlock(&mutex_); |
| 151 DCHECK_EQ(0, result); |
| 152 } |
| 153 pthread_mutex_t mutex_; |
| 154 |
| 155 #ifndef NDEBUG |
| 156 pthread_mutexattr_t mutex_attributes_; |
| 157 bool private_attributes_in_use_; |
| 158 #endif |
| 159 |
| 160 private: |
| 161 DISALLOW_COPY_AND_ASSIGN(PThreadMutex); |
| 162 }; |
| 163 |
| 164 class PThreadMutexAttr { |
| 165 public: |
| 166 pthread_mutexattr_t attr; |
| 167 inline PThreadMutexAttr(int type) { |
| 168 pthread_mutexattr_init(&attr); |
| 169 pthread_mutexattr_settype(&attr, type); |
| 170 } |
| 171 inline ~PThreadMutexAttr() { |
| 172 pthread_mutexattr_destroy(&attr); |
| 173 } |
| 174 private: |
| 175 DISALLOW_COPY_AND_ASSIGN(PThreadMutexAttr); |
| 176 }; |
| 177 |
| 178 class PThreadRecursiveMutex : public PThreadMutex { |
| 179 public: |
| 180 inline PThreadRecursiveMutex() : PThreadMutex(recursive_attr()) {} |
| 181 private: |
| 182 static inline pthread_mutexattr_t* recursive_attr() { |
| 183 static PThreadMutexAttr recursive(PTHREAD_MUTEX_RECURSIVE); |
| 184 return &recursive.attr; |
| 185 } |
| 186 DISALLOW_COPY_AND_ASSIGN(PThreadRecursiveMutex); |
| 187 }; |
| 188 |
| 189 |
| 190 class PThreadScopedDisabledCancellation { |
| 191 public: |
| 192 inline PThreadScopedDisabledCancellation() { |
| 193 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &old_cancel_state_); |
| 194 } |
| 195 inline ~PThreadScopedDisabledCancellation() { |
| 196 pthread_setcancelstate(old_cancel_state_, NULL); |
| 197 } |
| 198 private: |
| 199 int old_cancel_state_; |
| 200 |
| 201 DISALLOW_COPY_AND_ASSIGN(PThreadScopedDisabledCancellation); |
| 202 }; |
| 203 |
| 204 class PThreadCondVar { |
| 205 public: |
| 206 inline PThreadCondVar() { |
| 207 int result = pthread_cond_init(&condvar_, 0); |
| 208 DCHECK_EQ(0, result); |
| 209 } |
| 210 ~PThreadCondVar() { |
| 211 int result = pthread_cond_destroy(&condvar_); |
| 212 DCHECK_EQ(0, result); |
| 213 } |
| 214 inline void Signal() { |
| 215 int result = pthread_cond_signal(&condvar_); |
| 216 DCHECK_EQ(0, result); |
| 217 } |
| 218 inline void Broadcast() { |
| 219 int result = pthread_cond_broadcast(&condvar_); |
| 220 DCHECK_EQ(0, result); |
| 221 } |
| 222 pthread_cond_t condvar_; |
| 223 |
| 224 private: |
| 225 DISALLOW_COPY_AND_ASSIGN(PThreadCondVar); |
| 226 }; |
| 227 |
| 228 template <typename ValueType> |
| 229 class PThreadThreadVar { |
| 230 public: |
| 231 PThreadThreadVar(void (*destructor)(void* payload)) { |
| 232 int result = pthread_key_create(&thread_key_, destructor); |
| 233 DCHECK_EQ(0, result); |
| 234 } |
| 235 ~PThreadThreadVar() { |
| 236 int result = pthread_key_delete(thread_key_); |
| 237 DCHECK_EQ(0, result); |
| 238 } |
| 239 void SetValue(ValueType value) { |
| 240 int result = pthread_setspecific(thread_key_, static_cast<void*>(value)); |
| 241 DCHECK_EQ(0, result); |
| 242 } |
| 243 ValueType GetValue() { |
| 244 return static_cast<ValueType>(pthread_getspecific(thread_key_)); |
| 245 } |
| 246 private: |
| 247 pthread_key_t thread_key_; |
| 248 DISALLOW_COPY_AND_ASSIGN(PThreadThreadVar); |
| 249 }; |
| 250 |
| 251 // Returns the absolute time ms milliseconds from now. Useful for passing |
| 252 // result to pthread_cond_timedwait(). |
| 253 struct timespec GetPThreadAbsoluteTime(uint32 ms_from_now); |
| 254 |
| 255 // Assign a descriptive label to the current thread. This is useful to see |
| 256 // in a GUI debugger, but may not be implementable on all platforms. |
| 257 void NameCurrentThreadForDebugging(char* name); |
| 258 |
| 259 #endif // CHROME_BROWSER_SYNC_UTIL_PTHREAD_HELPERS_H_ |
OLD | NEW |