KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > sleepycat > je > latch > Java5SharedLatchImpl


1 /*-
2  * See the file LICENSE for redistribution information.
3  *
4  * Copyright (c) 2002,2006 Oracle. All rights reserved.
5  *
6  * $Id: Java5SharedLatchImpl.java,v 1.8 2006/11/29 19:57:56 mark Exp $
7  */

8
9 package com.sleepycat.je.latch;
10
11 import java.util.ArrayList JavaDoc;
12 import java.util.Collections JavaDoc;
13 import java.util.List JavaDoc;
14 import java.util.concurrent.locks.ReentrantReadWriteLock JavaDoc;
15
16 import com.sleepycat.je.DatabaseException;
17 import com.sleepycat.je.dbi.EnvironmentImpl;
18
19 /**
20  * Java5SharedLatchImpl provides an implementation of the SharedLatch
21  * interface. By using a wrapper class we can avoid link errors when we run in
22  * Java 1.4 JVMs. LatchSupport will only reference this class if it knows that
23  * the ReentrantReadWriteLock class is available at runtime through
24  * Class.forName(). LatchSupport only references this class through the
25  * SharedLatch interface and only constructs this using
26  *
27  * Class.forName("Java5SharedLatchImpl").newInstance();
28  */

29 class Java5SharedLatchImpl
30     extends ReentrantReadWriteLock JavaDoc
31     implements SharedLatch {
32
33     private String JavaDoc name;
34     private boolean noteLatch;
35     private List JavaDoc readers;
36
37     /**
38      * If true, this shared latch is only ever latched exclusively. Used for
39      * BINs.
40      */

41     private boolean exclusiveOnly;
42
43     Java5SharedLatchImpl() {
44     super(EnvironmentImpl.getFairLatches());
45     assert
46         (readers = Collections.synchronizedList(new ArrayList JavaDoc())) != null;
47     exclusiveOnly = false;
48     }
49
50     public void setExclusiveOnly(boolean exclusiveOnly) {
51     this.exclusiveOnly = exclusiveOnly;
52     }
53
54     /**
55      * Set the latch name, used for latches in objects instantiated from the
56      * log.
57      */

58     public void setName(String JavaDoc name) {
59     this.name = name;
60     }
61
62     /**
63      * If noteLatch is true, then track latch usage in the latchTable.
64      * Always return true so this can be called as an assert.
65      */

66     public boolean setNoteLatch(boolean noteLatch) {
67     this.noteLatch = noteLatch;
68     return true;
69     }
70
71     /**
72      * Acquire a latch for exclusive/write access.
73      *
74      * Wait for the latch if some other thread is holding it. If there are
75      * threads waiting for access, they will be granted the latch on a FIFO
76      * basis if fair latches are set. When the method returns, the latch is
77      * held for exclusive access.
78      *
79      * @throws LatchException if the latch is already held by the current
80      * thread for exclusive access.
81      */

82     public void acquireExclusive()
83     throws DatabaseException {
84
85         try {
86         if (isWriteLockedByCurrentThread()) {
87         throw new LatchException(name + " already held");
88         }
89
90         writeLock().lock();
91
92             assert (noteLatch ? noteLatch() : true);// intentional side effect;
93
} finally {
94         assert EnvironmentImpl.maybeForceYield();
95     }
96     }
97
98     public boolean acquireExclusiveNoWait()
99     throws DatabaseException {
100
101         try {
102         if (isWriteLockedByCurrentThread()) {
103         throw new LatchException(name + " already held");
104         }
105
106         boolean ret = writeLock().tryLock();
107
108         /* Intentional side effect. */
109             assert ((noteLatch & ret) ? noteLatch() : true);
110         return ret;
111     } finally {
112         assert EnvironmentImpl.maybeForceYield();
113     }
114     }
115
116     /**
117      * Acquire a latch for shared/read access.
118      */

119     public void acquireShared()
120         throws DatabaseException {
121
122     if (exclusiveOnly) {
123         acquireExclusive();
124         return;
125     }
126
127         try {
128         boolean assertionsEnabled = false;
129         assert assertionsEnabled = true;
130         if (assertionsEnabled) {
131         if (readers.add(Thread.currentThread())) {
132             readLock().lock();
133         } else {
134             /* Already latched, do nothing. */
135         }
136         } else {
137         readLock().lock();
138         }
139
140             assert (noteLatch ? noteLatch() : true);// intentional side effect
141
} finally {
142         assert EnvironmentImpl.maybeForceYield();
143     }
144     }
145
146     public boolean isOwner() {
147     boolean assertionsEnabled = false;
148     assert assertionsEnabled = true;
149     if (assertionsEnabled && !exclusiveOnly) {
150         return readers.contains(Thread.currentThread()) ||
151         isWriteLockedByCurrentThread();
152     } else {
153         return isWriteLockedByCurrentThread();
154     }
155     }
156
157     /**
158      * Release an exclusive or shared latch. If there are other thread(s)
159      * waiting for the latch, they are woken up and granted the latch.
160      */

161     public void release()
162     throws LatchNotHeldException {
163
164     try {
165         if (isWriteLockedByCurrentThread()) {
166         writeLock().unlock();
167                 /* Intentional side effect. */
168                 assert (noteLatch ? unNoteLatch() : true);
169         return;
170         }
171
172         if (exclusiveOnly) {
173         return;
174         }
175
176         boolean assertionsEnabled = false;
177         assert assertionsEnabled = true;
178         if (assertionsEnabled) {
179         if (readers.remove(Thread.currentThread())) {
180             readLock().unlock();
181         } else {
182             throw new LatchNotHeldException(name + " not held");
183         }
184         } else {
185
186         /*
187          * There's no way to tell if a readlock is held by the current
188          * thread so just try unlocking it.
189          */

190         readLock().unlock();
191         }
192         /* Intentional side effect. */
193         assert (noteLatch ? unNoteLatch() : true);
194     } catch (IllegalMonitorStateException JavaDoc IMSE) {
195         IMSE.printStackTrace();
196         return;
197     }
198     }
199
200     public void releaseIfOwner()
201     throws LatchNotHeldException {
202
203     if (isWriteLockedByCurrentThread()) {
204         writeLock().unlock();
205         assert (noteLatch ? unNoteLatch() : true);
206         return;
207     }
208
209     if (exclusiveOnly) {
210         return;
211     }
212
213     assert (getReadLockCount() > 0);
214     boolean assertionsEnabled = false;
215     assert assertionsEnabled = true;
216     if (assertionsEnabled) {
217         if (readers.contains(Thread.currentThread())) {
218         readLock().unlock();
219         assert (noteLatch ? unNoteLatch() : true);
220         }
221     } else {
222
223         /*
224          * There's no way to tell if a readlock is held by the current
225          * thread so just try unlocking it.
226          */

227         readLock().unlock();
228     }
229     }
230
231     /**
232      * Only call under the assert system. This records latching by thread.
233      */

234     private boolean noteLatch()
235     throws LatchException {
236
237         return LatchSupport.latchTable.noteLatch(this);
238     }
239
240     /**
241      * Only call under the assert system. This records latching by thread.
242      */

243     private boolean unNoteLatch() {
244         
245     return LatchSupport.latchTable.unNoteLatch(this, name);
246     }
247 }
248
Popular Tags