Source code: jacomma/util/RdWrLock.java
1 /*
2 * $Source: /home/data/cvsroot/src/jacomma/util/RdWrLock.java,v $
3 * $Revision: 1.4 $
4 * $Date: 2000/10/28 20:09:08 $
5 *
6 * This file is part of the jacomma framework
7 * Copyright (c) 2000 Dimitrios Vyzovitis
8 * mailto:dviz@egnatia.ee.auth.gr
9 *
10 *
11 *
12 *
13 *
14 *
15 * This library is free software; you can redistribute it and/or modify
16 * it under the terms of the GNU Library General Public License as published by
17 * the Free Software Foundation; either version 2 of the License, or
18 * (at your option) any later version.
19 *
20 * This library is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 * GNU Library General Public License for more details.
24 *
25 * You should have received a copy of the GNU Library General Public License
26 * along with this library; if not, write to the Free Software
27 * Foundation, Inc., 59 Temple Place, Suite 330,
28 * Boston, MA 02111-1307 USA
29 */
30
31 package jacomma.util;
32
33 /**
34 * A recursive (re-enterant) read-write Lock implementation with single reader
35 * priviledge elevation and deadlock detection
36 **/
37 public class RdWrLock {
38
39 private java.util.Map readers_;
40 private LockCount writer_;
41
42 public RdWrLock( ) {
43 readers_ = new java.util.HashMap( );
44 }
45
46 public synchronized void rdlock() {
47 try {
48 while( !_try_rdlock() ) {
49 // Attempt to fix the 100% CPU utilization behavior incurred by LinuxThreads
50 Thread.currentThread().yield();
51 wait();
52 }
53 } catch ( InterruptedException exc ) {
54 throw new CheckedException( exc );
55 }
56 }
57
58 /**
59 * Acquires a write-lock.
60 */
61 public synchronized void wrlock() {
62 try {
63 while( !_try_wrlock() )
64 if ( readers_.containsKey( Thread.currentThread() ) )
65 // priviledge elevation attempt failed
66 throw new IllegalStateException( "Potential Deadlock: Failed to elevate priviledges of Reader thread: " + Thread.currentThread() );
67 else {
68 // Attempt to fix the 100% CPU utilization behavior incurred by LinuxThreads
69 Thread.currentThread().yield();
70 wait();
71 }
72 } catch ( InterruptedException exc ) {
73 throw new CheckedException( exc );
74 }
75 }
76
77
78 /**
79 * @return true if a read-lock is successfully acquired.
80 */
81 public synchronized boolean try_rdlock() {
82 return _try_rdlock();
83 }
84
85 /**
86 * @return true if a write-lock is succesfully acquired
87 */
88 public synchronized boolean try_wrlock() {
89 return _try_wrlock();
90 }
91
92 /**
93 * Releases (decrements count) a lock ownder by the current thread
94 * Nothing happens if the thread is not a lock owner
95 */
96 public synchronized void unlock() {
97 if ( writer_ == null ) {
98 LockCount rd = (LockCount)readers_.get( Thread.currentThread() );
99 if ( rd != null
100 && rd.down() == 0 ) {
101 readers_.remove( rd.thread_ );
102 notify(); // only writers are waiting - notify one of them
103 }
104 } else if ( writer_.thread_ == Thread.currentThread()
105 && writer_.down() == 0 ) {
106 writer_ = null;
107 notifyAll(); // potentially many readers and/or writers are waiting.
108 }
109 }
110
111 private boolean _try_rdlock() {
112
113 if ( writer_ == null ) {
114 LockCount count = (LockCount)readers_.get( Thread.currentThread() );
115 if ( count == null ) {
116 count = new LockCount( );
117 readers_.put( count.thread_, count );
118 }
119 count.up();
120 return true;
121 } else if ( writer_.thread_ == Thread.currentThread() ) {
122 writer_.up();
123 return true;
124 } else
125 return false;
126
127 }
128
129 private boolean _try_wrlock() {
130 if ( writer_ == null ) {
131 writer_ = (LockCount)readers_.remove( Thread.currentThread() );
132 if ( readers_.size() > 0 ) {
133
134 if ( writer_ != null ) {
135 // put back
136 readers_.put( writer_.thread_, writer_ );
137 writer_ = null;
138 return false;
139 }
140
141 } else if ( writer_ == null )
142 writer_ = new LockCount( );
143
144 } else if ( writer_.thread_ != Thread.currentThread() ) {
145 return false;
146 }
147
148 writer_.up();
149 return true;
150 }
151
152 private class LockCount {
153 Thread thread_ = Thread.currentThread();
154 int count_ = 0;;
155
156 int up() { return ++count_; }
157 int down() { return --count_; }
158
159 }
160
161 }