root/trunk/dep/include/zthread/BiasedReadWriteLock.h @ 2

Revision 2, 6.3 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 __ZTBIASEDREADWRITELOCK_H__
24#define __ZTBIASEDREADWRITELOCK_H__
25
26#include "zthread/ReadWriteLock.h"
27#include "zthread/Condition.h"
28#include "zthread/Guard.h"
29#include "zthread/FastMutex.h"
30
31namespace ZThread {
32
33  /**
34   * @class BiasedReadWriteLock
35   *
36   * @author Eric Crahen <http://www.code-foo.com>
37   * @date <2003-07-16T10:22:34-0400>
38   * @version 2.2.7
39   * 
40   * A BiasedReadWriteLock has a bias toward writers. It will prefer read-write access over
41   * read-only access when many threads are contending for access to either Lockable this
42   * ReadWriteLock provides.
43   *
44   * @see ReadWriteLock
45   */
46  class BiasedReadWriteLock : public ReadWriteLock {
47
48    FastMutex _lock;
49    Condition _condRead;
50    Condition _condWrite;
51 
52    volatile int _activeWriters;
53    volatile int _activeReaders; 
54
55    volatile int _waitingReaders;
56    volatile int _waitingWriters;
57
58    //! @class ReadLock
59    class ReadLock : public Lockable {
60
61      BiasedReadWriteLock& _rwlock;
62
63    public:
64
65      ReadLock(BiasedReadWriteLock& rwlock) : _rwlock(rwlock) {}
66
67      virtual ~ReadLock() {}
68
69      virtual void acquire() {
70        _rwlock.beforeRead();
71      }
72
73      virtual bool tryAcquire(unsigned long timeout) {           
74        return _rwlock.beforeReadAttempt(timeout);
75      }
76
77      virtual void release() {
78        _rwlock.afterRead();
79      }
80
81    };
82
83    //! @class WriteLock
84    class WriteLock : public Lockable {
85
86      BiasedReadWriteLock& _rwlock;
87
88    public:
89
90      WriteLock(BiasedReadWriteLock& rwlock) : _rwlock(rwlock) {}
91
92      virtual ~WriteLock() {}
93
94
95      virtual void acquire() {
96        _rwlock.beforeWrite();
97      }
98
99      virtual bool tryAcquire(unsigned long timeout) {           
100        return _rwlock.beforeWriteAttempt(timeout);
101      }
102
103      virtual void release() {
104        _rwlock.afterWrite();
105      }
106
107    };
108
109    friend class ReadLock;
110    friend class WriteLock;
111
112    ReadLock _rlock;
113    WriteLock _wlock;
114
115  public:
116 
117    /**
118     * Create a BiasedReadWriteLock
119     *
120     * @exception Initialization_Exception thrown if resources could not be
121     *            allocated for this object.
122     */
123    BiasedReadWriteLock() : _condRead(_lock), _condWrite(_lock), _rlock(*this), _wlock(*this) {
124
125      _activeWriters = 0;
126      _activeReaders = 0;
127 
128      _waitingReaders = 0;
129      _waitingWriters = 0;
130
131    }
132
133    //! Destroy this ReadWriteLock
134    virtual ~BiasedReadWriteLock() {}
135
136    /**
137     * @see ReadWriteLock::getReadLock()
138     */
139    virtual Lockable& getReadLock() { return _rlock; }
140
141    /**
142     * @see ReadWriteLock::getWriteLock()
143     */
144    virtual Lockable& getWriteLock() { return _wlock; }
145
146 
147  protected:
148
149    void beforeRead() {
150   
151      Guard<FastMutex> guard(_lock); 
152   
153      ++_waitingReaders; 
154   
155      while(!allowReader()) {
156     
157        try {
158       
159          // wait
160          _condRead.wait();
161       
162        } catch(...) {
163       
164          --_waitingReaders;       
165          throw;
166
167        }
168     
169      }
170   
171      --_waitingReaders;
172      ++_activeReaders;
173   
174    }
175
176    bool beforeReadAttempt(unsigned long timeout) {
177     
178      Guard<FastMutex> guard(_lock); 
179      bool result = false;
180
181      ++_waitingReaders; 
182
183      while(!allowReader()) {
184       
185        try {
186         
187          result = _condRead.wait(timeout);
188         
189        } catch(...) {
190         
191          --_waitingReaders;         
192          throw;
193
194        }
195
196      }
197     
198      --_waitingReaders;
199      ++_activeReaders;
200
201      return result;
202    }   
203 
204
205    void afterRead() {
206
207      bool wakeReader = false;
208      bool wakeWriter = false;
209
210      {
211
212        Guard<FastMutex> guard(_lock);
213     
214        --_activeReaders;
215
216        wakeReader = (_waitingReaders > 0);
217        wakeWriter = (_waitingWriters > 0);
218
219      }
220
221      if(wakeWriter)
222        _condWrite.signal();
223   
224      else if(wakeReader)
225        _condRead.signal();
226
227    }
228
229    void beforeWrite() {
230   
231      Guard<FastMutex> guard(_lock);
232 
233      ++_waitingWriters;
234
235      while(!allowWriter()) {
236       
237        try {
238
239          _condWrite.wait();
240         
241        } catch(...) {
242
243          --_waitingWriters;
244          throw;
245
246        }
247       
248      }
249     
250      --_waitingWriters;
251      ++_activeWriters;   
252
253    }
254
255    bool beforeWriteAttempt(unsigned long timeout) {
256 
257      Guard<FastMutex> guard(_lock);
258      bool result = false;
259
260      ++_waitingWriters;
261
262      while(!allowWriter()) {
263       
264        try {
265
266          result = _condWrite.wait(timeout);
267         
268        } catch(...) {
269
270          --_waitingWriters;
271          throw;
272        }
273       
274      }
275     
276      --_waitingWriters;
277      ++_activeWriters;
278     
279      return result;
280
281    }
282
283    void afterWrite() {
284
285      bool wakeReader = false;
286      bool wakeWriter = false;
287
288      {
289
290        Guard<FastMutex> guard(_lock);
291     
292        --_activeWriters;
293     
294        wakeReader = (_waitingReaders > 0);
295        wakeWriter = (_waitingWriters > 0);
296
297      }
298
299      if(wakeWriter)
300        _condWrite.signal();
301   
302      else if(wakeReader)
303        _condRead.signal();
304   
305    }
306
307    bool allowReader() {
308      return (_activeWriters == 0);   
309    }
310
311    bool allowWriter() {
312      return (_activeWriters == 0 && _activeReaders == 0);
313    }
314
315  };
316
317}; // __ZTBIASEDREADWRITELOCK_H__
318
319#endif
Note: See TracBrowser for help on using the browser.