2 * Copyright (c) 2005, Eric Crahen
4 * Permission is hereby granted, free of charge, to any person obtaining a copy
5 * of this software and associated documentation files (the "Software"), to deal
6 * in the Software without restriction, including without limitation the rights
7 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 * copies of the Software, and to permit persons to whom the Software is furnished
9 * to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice shall be included in all
12 * copies or substantial portions of the Software.
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
18 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 #ifndef __ZTFASTRECURSIVELOCK_H__
24 #define __ZTFASTRECURSIVELOCK_H__
26 #include "zthread/NonCopyable.h"
34 * @class FastRecursiveLock
36 * @author Eric Crahen <http://www.code-foo.com>
37 * @date <2003-07-16T23:28:37-0400>
40 * This is an implementation of a FastRecursiveLock for any vannila
41 * POSIX system. It is based on a condition variable and a mutex;
42 * because of this it is important to not that its waiting properties
43 * are not the same as other mutex implementations that generally
44 * based on spin locks. Under high contention, this implementation may
45 * be preferable to a spin lock, although refactoring the design of
46 * code that puts a mutex under alot of preasure may be worth investigating.
48 class FastRecursiveLock
: private NonCopyable
{
60 volatile unsigned int _count
;
64 inline FastRecursiveLock() : _owner(0), _count(0) {
66 pthread_mutex_init(&_mtx
, 0);
67 if(pthread_cond_init(&_cond
, 0) != 0) {
73 inline ~FastRecursiveLock() {
75 pthread_mutex_destroy(&_mtx
);
76 if(pthread_cond_destroy(&_cond
) != 0) {
82 inline void acquire() {
84 pthread_t self
= pthread_self();
85 pthread_mutex_lock(&_mtx
);
87 // If the caller does not own the lock, wait until there is no owner
88 if(_owner
!= 0 && !pthread_equal(_owner
, self
)) {
91 do { // ignore signals
92 status
= pthread_cond_wait(&_cond
, &_mtx
);
93 } while(status
== EINTR
&& _owner
== 0);
100 pthread_mutex_unlock(&_mtx
);
104 inline bool tryAcquire(unsigned long timeout
=0) {
106 pthread_t self
= pthread_self();
107 pthread_mutex_lock(&_mtx
);
109 // If the caller owns the lock, or there is no owner update the count
110 bool success
= (_owner
== 0 || pthread_equal(_owner
, self
));
118 pthread_mutex_unlock(&_mtx
);
124 inline void release() {
126 assert(pthread_equal(_owner
, pthread_self()));
128 pthread_mutex_lock(&_mtx
);
132 pthread_cond_signal(&_cond
);
136 pthread_mutex_unlock(&_mtx
);
141 }; /* FastRecursiveLock */
144 } // namespace ZThread