KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > continuent > sequoia > controller > locks > ReadPrioritaryFIFOWriteLock


1 /**
2  * Sequoia: Database clustering technology.
3  * Copyright (C) 2002-2004 French National Institute For Research In Computer
4  * Science And Control (INRIA).
5  * Contact: sequoia@continuent.org
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  * http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  * Initial developer(s): Emmanuel Cecchet.
20  * Contributor(s): ______________________.
21  */

22
23 package org.continuent.sequoia.controller.locks;
24
25 import java.util.ArrayList JavaDoc;
26
27 /**
28  * Reader/Writer lock with write priority.
29  * <p>
30  * If a reader holds the lock, all incoming readers are allowed to acquire the
31  * lock until a write arrives. A writer must wait for all current readers to
32  * release the lock before acquiring it. <br>
33  * When a writer has the lock, everybody else is blocked. <br>
34  * When a writer release the lock, there is a writer priority so if another
35  * writer is waiting it will have the lock even if it arrived later than
36  * readers. Writers are prioritary against readers but all writers get the lock
37  * in a FIFO order.
38  *
39  * @author <a HREF="mailto:Emmanuel.Cecchet@inria.fr">Emmanuel Cecchet </a>
40  * @version 1.0
41  */

42 public class ReadPrioritaryFIFOWriteLock
43 {
44   /** Threads executing read. */
45   private int activeReaders;
46
47   /** Is there an active writer? */
48   private boolean activeWriter;
49
50   /** Threads not yet in read. */
51   private int waitingReaders;
52
53   /** Threads not yet in write. */
54   private int waitingWriters;
55
56   private Object JavaDoc readSync;
57   private ArrayList JavaDoc writeWaitingQueue;
58
59   /**
60    * Creates a new <code>ReadPrioritaryFIFOWriteLock</code> instance.
61    */

62   public ReadPrioritaryFIFOWriteLock()
63   {
64     activeReaders = 0;
65     activeWriter = false;
66     waitingReaders = 0;
67     waitingWriters = 0;
68     readSync = new Object JavaDoc();
69     writeWaitingQueue = new ArrayList JavaDoc();
70   }
71
72   /**
73    * Acquires the lock for a read.
74    *
75    * @throws InterruptedException if wait failed (the lock should remain in a
76    * correct state)
77    */

78   public void acquireRead() throws InterruptedException JavaDoc
79   {
80     synchronized (this)
81     {
82       if ((waitingWriters == 0) && !activeWriter)
83       { // No active or pending writer
84
activeReaders++;
85         return;
86       }
87     }
88
89     // Beyond this point, we have to wait
90
synchronized (readSync)
91     {
92       // It becomes a little bit tricky here but a writer could have
93
// released the lock between the first test at the beginning of
94
// this function and this point. Therefore we have to recheck if
95
// the lock is not completely idle else we'll never wake up !
96
synchronized (this)
97       {
98         if (!activeWriter)
99         { // No active or pending writer
100
activeReaders++;
101           return;
102         }
103       }
104
105       waitingReaders++;
106       try
107       {
108         readSync.wait();
109       }
110       catch (InterruptedException JavaDoc ie)
111       {
112         waitingReaders--; // roll back state
113
throw ie;
114       }
115       waitingReaders--;
116     }
117     synchronized (this)
118     {
119       activeReaders++;
120     }
121   }
122
123   /**
124    * Releases a lock previously acquired for reading.
125    */

126   public synchronized void releaseRead()
127   {
128     activeReaders--;
129     if ((activeReaders == 0) && (waitingWriters > 0))
130     { // Wake up first waiting write if any
131
Object JavaDoc thread = writeWaitingQueue.remove(0);
132       synchronized (thread)
133       {
134         thread.notify();
135         activeWriter = true;
136         waitingWriters--;
137       }
138     }
139   }
140
141   /**
142    * Acquires the lock for a write.
143    *
144    * @throws InterruptedException if wait failed (the lock should remain in a
145    * correct state)
146    */

147   public void acquireWrite() throws InterruptedException JavaDoc
148   {
149     synchronized (Thread.currentThread())
150     {
151       synchronized (this)
152       {
153         if ((activeReaders == 0) && !activeWriter)
154         {
155           activeWriter = true;
156           return;
157         }
158         else
159         {
160           waitingWriters++;
161           writeWaitingQueue.add(Thread.currentThread());
162         }
163       }
164       try
165       {
166         Thread.currentThread().wait();
167       }
168       catch (InterruptedException JavaDoc ie)
169       {
170         releaseWrite();
171         throw ie;
172       }
173     }
174   }
175
176   /**
177    * Releases a lock previously acquired for writing.
178    */

179   public void releaseWrite()
180   {
181     // Writer priority
182
synchronized (this)
183     {
184       activeWriter = false;
185       if (waitingWriters > 0)
186       { // Wake up first waiting write if any
187
Object JavaDoc thread = writeWaitingQueue.remove(0);
188         synchronized (thread)
189         {
190           thread.notify();
191           activeWriter = true;
192           waitingWriters--;
193         }
194         return;
195       }
196     }
197
198     // Wake up readers
199
//
200
// Note that we cannot do the following inside synchronized(this) because
201
// acquireRead() takes synchronized(readSync) first and then
202
// synchronized(this).
203
synchronized (readSync)
204     {
205       if (waitingReaders > 0)
206         readSync.notifyAll();
207     }
208   }
209
210   /**
211    * Tests if the lock is currently held by at least one reader.
212    *
213    * @return <code>true</code> if the lock is held by a reader
214    */

215   public final synchronized boolean isReadLocked()
216   {
217     return activeReaders > 0;
218   }
219
220   /**
221    * Tests if the lock is currently held by a writer.
222    *
223    * @return <code>true</code> if the lock is held by a writer
224    */

225   public final synchronized boolean isWriteLocked()
226   {
227     return activeWriter;
228   }
229 }
Popular Tags