root/trunk/dep/src/zthread/vanilla/DualMutexRecursiveLock.h @ 2

Revision 2, 3.9 kB (checked in by yumileroy, 17 years ago)

[svn] * Proper SVN structure

Original author: Neo2003
Date: 2008-10-02 16:23:55-05:00

Line 
1/*
2 * Copyright (c) 2005, Eric Crahen
3 *
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:
10 *
11 * The above copyright notice and this permission notice shall be included in all
12 * copies or substantial portions of the Software.
13 *
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.
20 *
21 */
22
23#ifndef __ZTFASTRECURSIVELOCK_H__
24#define __ZTFASTRECURSIVELOCK_H__
25
26#include "../FastLock.h"
27#include "../ThreadOps.h"
28#include <assert.h>
29
30namespace ZThread {
31
32/**
33 * @class FastRecursiveLock
34 *
35 * @author Eric Crahen <http://www.code-foo.com>
36 * @date <2003-07-16T23:31:09-0400>
37 * @version 2.2.8
38 *
39 * This is a vanilla FastRecursiveLock implementation for a
40 * system that doesn't provide recurisve locks. This implementation
41 * is based on using a pair of mutexes, because of this, it performs
42 * roughly the same as a spin lock would.
43 */ 
44class FastRecursiveLock : private NonCopyable {
45   
46  //! Lock for blocking
47  FastLock _blockingLock;
48
49  //! Serialize state
50  FastLock _stateLock;
51
52  //! Owner
53  ThreadOps _owner;
54
55  //! Count
56  volatile unsigned int _count;
57
58 public:
59
60  inline FastRecursiveLock() : _owner(ThreadOps::INVALID), _count(0) { }
61 
62  inline ~FastRecursiveLock() {
63
64    assert(_owner == ThreadOps::INVALID);
65    assert(_count == 0);
66
67  }
68 
69  void acquire() {
70
71    ThreadOps self(ThreadOps::self());
72
73    // Try to lock the blocking mutex first
74    bool wasLocked = _blockingLock.tryAcquire();
75    if(!wasLocked) {
76   
77      // Otherwise, grab the lock for the state
78      _stateLock.acquire();
79
80      wasLocked = (_owner == self);
81      if(wasLocked)
82        _count++;
83
84      _stateLock.release();
85     
86      if(wasLocked)
87        return;
88
89      // Try to be cooperative
90      ThreadOps::yield();
91      _blockingLock.acquire();
92     
93    }
94
95    // Serialze access to the state
96    _stateLock.acquire();
97   
98    // Take ownership   
99    assert(_owner == ThreadOps::INVALID || _owner == self);
100
101    _owner = self;
102    _count++;
103     
104    _stateLock.release();
105
106  }
107 
108 
109  bool tryAcquire(unsigned long timeout = 0) {
110
111    ThreadOps self(ThreadOps::self());
112
113    // Try to lock the blocking mutex first
114    bool wasLocked = _blockingLock.tryAcquire();
115    if(!wasLocked) {
116   
117      // Otherwise, grab the lock for the state
118      _stateLock.acquire();
119
120      wasLocked = (_owner == self);
121      if(wasLocked)
122        _count++;
123
124      _stateLock.release();
125     
126      return wasLocked;
127     
128    }
129
130    // Serialze access to the state
131    _stateLock.acquire();
132   
133    // Take ownership   
134    assert(_owner == ThreadOps::INVALID || _owner == self);
135
136    _owner = self;
137    _count++;
138     
139    _stateLock.release();
140   
141    return true;
142
143  }
144
145   
146  void release() {
147
148    // Assume that release is only used by the owning thread, as it
149    // should be.
150    assert(_count != 0);
151    assert(_owner == ThreadOps::self());
152   
153    _stateLock.acquire();
154   
155    // If the lock was owned and the count has reached 0, give up
156    // ownership and release the blocking lock
157    if(--_count == 0) {
158     
159      _owner = ThreadOps::INVALID;
160      _blockingLock.release();
161     
162    }
163   
164    _stateLock.release();
165
166  }
167 
168
169}; /* FastRecursiveLock */
170
171} // namespace ZThread
172
173#endif
Note: See TracBrowser for help on using the browser.