KickJava   Java API By Example, From Geeks To Geeks.

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


1 /*-
2  * See the file LICENSE for redistribution information.
3  *
4  * Copyright (c) 2002,2006 Oracle. All rights reserved.
5  *
6  * $Id: Java5LatchImpl.java,v 1.9 2006/10/30 21:14:19 bostic Exp $
7  */

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

26 class Java5LatchImpl implements Latch {
27
28     /*
29      * Required because getOwner() is protected (for unknown reasons) and can't
30      * be accessed except by a subclass of ReentrantLock.
31      */

32     static private class JEReentrantLock extends ReentrantLock JavaDoc {
33     JEReentrantLock(boolean fair) {
34         super(fair);
35     }
36
37     protected Thread JavaDoc getOwner() {
38         return super.getOwner();
39     }
40     }
41
42     private JEReentrantLock lock;
43     private String JavaDoc name;
44     private LatchStats stats = new LatchStats();
45
46     Java5LatchImpl() {
47     lock = new JEReentrantLock(EnvironmentImpl.getFairLatches());
48     }
49
50     /**
51      * Set the latch name, used for latches in objects instantiated from
52      * the log.
53      */

54     public void setName(String JavaDoc name) {
55     this.name = name;
56     }
57
58     /**
59      * Acquire a latch for exclusive/write access.
60      *
61      * <p>Wait for the latch if some other thread is holding it. If there are
62      * threads waiting for access, they will be granted the latch on a FIFO
63      * basis. When the method returns, the latch is held for exclusive
64      * access.</p>
65      *
66      * @throws LatchException if the latch is already held by the calling
67      * thread.
68      */

69     public void acquire()
70     throws DatabaseException {
71
72         try {
73         if (lock.isHeldByCurrentThread()) {
74         stats.nAcquiresSelfOwned++;
75         throw new LatchException(name + " already held");
76         }
77
78         if (lock.isLocked()) {
79         stats.nAcquiresWithContention++;
80         } else {
81         stats.nAcquiresNoWaiters++;
82         }
83
84         lock.lock();
85
86             assert noteLatch(); // intentional side effect;
87
} finally {
88         assert EnvironmentImpl.maybeForceYield();
89     }
90     }
91
92     /**
93      * Acquire a latch for exclusive/write access, but do not block if it's not
94      * available.
95      *
96      * @return true if the latch was acquired, false if it is not available.
97      *
98      * @throws LatchException if the latch is already held by the calling
99      * thread.
100      */

101     public boolean acquireNoWait()
102     throws LatchException {
103         try {
104         if (lock.isHeldByCurrentThread()) {
105         stats.nAcquiresSelfOwned++;
106         throw new LatchException(name + " already held");
107         }
108
109         boolean ret = lock.tryLock();
110         if (ret) {
111         assert noteLatch();
112         stats.nAcquireNoWaitSuccessful++;
113         } else {
114         stats.nAcquireNoWaitUnsuccessful++;
115         }
116         return ret;
117     } finally {
118         assert EnvironmentImpl.maybeForceYield();
119     }
120     }
121
122     /**
123      * Release the latch. If there are other thread(s) waiting for the latch,
124      * one is woken up and granted the latch. If the latch was not owned by
125      * the caller, just return;
126      */

127     public void releaseIfOwner() {
128     doRelease(false);
129     }
130
131     /**
132      * Release the latch. If there are other thread(s) waiting for the latch,
133      * they are woken up and granted the latch.
134      *
135      * @throws LatchNotHeldException if the latch is not currently held.
136      */

137     public void release()
138     throws LatchNotHeldException {
139
140     if (doRelease(true)) {
141             throw new LatchNotHeldException(name + " not held");
142         }
143     }
144
145     /**
146      * Do the work of releasing the latch. Wake up any waiters.
147      *
148      * @returns true if this latch was not owned by the caller.
149      */

150     private boolean doRelease(boolean checkHeld) {
151
152     try {
153         if (!lock.isHeldByCurrentThread()) {
154         return true;
155         }
156         lock.unlock();
157         stats.nReleases++;
158         assert unNoteLatch(checkHeld); // intentional side effect.
159
} catch (IllegalMonitorStateException JavaDoc IMSE) {
160         return true;
161     }
162     return false;
163     }
164
165     /**
166      * Return true if the current thread holds this latch.
167      *
168      * @return true if we hold this latch. False otherwise.
169      */

170     public boolean isOwner() {
171     return lock.isHeldByCurrentThread();
172     }
173
174     /**
175      * Used only for unit tests.
176      *
177      * @return the thread that currently holds the latch for exclusive access.
178      */

179     public Thread JavaDoc owner() {
180     return lock.getOwner();
181     }
182
183     /**
184      * Return the number of threads waiting.
185      *
186      * @return the number of threads waiting for the latch.
187      */

188     public int nWaiters() {
189     return lock.getQueueLength();
190     }
191
192     /**
193      * @return a LatchStats object with information about this latch.
194      */

195     public LatchStats getLatchStats() {
196     LatchStats s = null;
197     try {
198         s = (LatchStats) stats.clone();
199     } catch (CloneNotSupportedException JavaDoc e) {
200         /* Klockwork - ok */
201     }
202     return s;
203     }
204
205     /**
206      * Formats a latch owner and waiters.
207      */

208     public String JavaDoc toString() {
209     return lock.toString();
210     }
211
212     /**
213      * Only call under the assert system. This records latching by thread.
214      */

215     private boolean noteLatch()
216     throws LatchException {
217
218         return LatchSupport.latchTable.noteLatch(this);
219     }
220
221     /**
222      * Only call under the assert system. This records latching by thread.
223      */

224     private boolean unNoteLatch(boolean checkHeld) {
225         
226         /* Only return a false status if we are checking for latch ownership.*/
227         if (checkHeld) {
228             return LatchSupport.latchTable.unNoteLatch(this, name);
229         } else {
230             LatchSupport.latchTable.unNoteLatch(this, name);
231             return true;
232         }
233     }
234 }
235
Popular Tags