KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > avalon > excalibur > concurrent > DijkstraSemaphore


1 /*
2
3  ============================================================================
4                    The Apache Software License, Version 1.1
5  ============================================================================
6  
7  Copyright (C) 1999-2003 The Apache Software Foundation. All rights reserved.
8  
9  Redistribution and use in source and binary forms, with or without modifica-
10  tion, are permitted provided that the following conditions are met:
11  
12  1. Redistributions of source code must retain the above copyright notice,
13     this list of conditions and the following disclaimer.
14  
15  2. Redistributions in binary form must reproduce the above copyright notice,
16     this list of conditions and the following disclaimer in the documentation
17     and/or other materials provided with the distribution.
18  
19  3. The end-user documentation included with the redistribution, if any, must
20     include the following acknowledgment: "This product includes software
21     developed by the Apache Software Foundation (http://www.apache.org/)."
22     Alternately, this acknowledgment may appear in the software itself, if
23     and wherever such third-party acknowledgments normally appear.
24  
25  4. The names "Jakarta", "Avalon", "Excalibur" and "Apache Software Foundation"
26     must not be used to endorse or promote products derived from this software
27     without prior written permission. For written permission, please contact
28     apache@apache.org.
29  
30  5. Products derived from this software may not be called "Apache", nor may
31     "Apache" appear in their name, without prior written permission of the
32     Apache Software Foundation.
33  
34  THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
35  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
36  FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
37  APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
38  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU-
39  DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
40  OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
41  ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
42  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
43  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
44  
45  This software consists of voluntary contributions made by many individuals
46  on behalf of the Apache Software Foundation. For more information on the
47  Apache Software Foundation, please see <http://www.apache.org/>.
48  
49 */

50 package org.apache.avalon.excalibur.concurrent;
51
52 /**
53  * Also called counting semaphores, Djikstra semaphores are used to control
54  * access to a set of resources. A Djikstra semaphore has a count associated
55  * with it and each acquire() call reduces the count. A thread that tries to
56  * acquire() a Djikstra semaphore with a zero count blocks until someone else
57  * calls release() thus increasing the count.
58  *
59  * @deprecated use EDU.oswego.cs.dl.util.concurrent.Semaphore instead
60  *
61  * @author <a HREF="mailto:kranga@sapient.com">Karthik Rangaraju</a>
62  * @version CVS $Revision: 1.5 $ $Date: 2003/04/05 19:39:33 $
63  * @since 4.0
64  */

65 public class DijkstraSemaphore
66 {
67     private int m_count;
68     private int m_maxCount;
69     private Object JavaDoc m_starvationLock = new Object JavaDoc();
70
71     /**
72      * Creates a Djikstra semaphore with the specified max count and initial
73      * count set to the max count (all resources released).
74      *
75      * @param maxCount is the max semaphores that can be acquired
76      */

77     public DijkstraSemaphore( int maxCount )
78     {
79         this( maxCount, maxCount );
80     }
81
82     /**
83      * Creates a Djikstra semaphore with the specified max count and an initial
84      * count of acquire() operations that are assumed to have already been
85      * performed.
86      *
87      * @param maxCount is the max semaphores that can be acquired
88      * @param initialCount is the current count (setting it to zero means all
89      * semaphores have already been acquired). 0 <= initialCount <= maxCount
90      */

91     public DijkstraSemaphore( int maxCount, int initialCount )
92     {
93         m_count = initialCount;
94         m_maxCount = maxCount;
95     }
96
97     /**
98      * If the count is non-zero, acquires a semaphore and decrements the count
99      * by 1, otherwise blocks until a release() is executed by some other thread.
100      *
101      * @throws InterruptedException is the thread is interrupted when blocked
102      * @see #tryAcquire()
103      * @see #acquireAll()
104      */

105     public void acquire()
106         throws InterruptedException JavaDoc
107     {
108         synchronized( this )
109         {
110             // Using a spin lock to take care of rogue threads that can enter
111
// before a thread that has exited the wait state acquires the monitor
112
while( m_count == 0 )
113             {
114                 wait();
115             }
116             m_count--;
117             synchronized( m_starvationLock )
118             {
119                 if( m_count == 0 )
120                 {
121                     m_starvationLock.notify();
122                 }
123             }
124         }
125     }
126
127     /**
128      * Non-blocking version of acquire().
129      *
130      * @return true if semaphore was acquired (count is decremented by 1), false
131      * otherwise
132      */

133     public boolean tryAcquire()
134     {
135         synchronized( this )
136         {
137             if( m_count != 0 )
138             {
139                 m_count--;
140                 synchronized( m_starvationLock )
141                 {
142                     if( m_count == 0 )
143                     {
144                         m_starvationLock.notify();
145                     }
146                 }
147                 return true;
148             }
149             else
150             {
151                 return false;
152             }
153         }
154     }
155
156     /**
157      * Releases a previously acquires semaphore and increments the count by one.
158      * Does not check if the thread releasing the semaphore was a thread that
159      * acquired the semaphore previously. If more releases are performed than
160      * acquires, the count is not increased beyond the max count specified during
161      * construction.
162      *
163      * @see #release( int count )
164      * @see #releaseAll()
165      */

166     public void release()
167     {
168         synchronized( this )
169         {
170             m_count++;
171             if( m_count > m_maxCount )
172             {
173                 m_count = m_maxCount;
174             }
175             notify();
176         }
177     }
178
179     /**
180      * Same as release() except that the count is increased by pCount instead
181      * of 1. The resulting count is capped at max count specified in the
182      * constructor.
183      *
184      * @param count is the amount by which the counter should be incremented
185      * @see #release()
186      */

187     public void release( int count )
188     {
189         synchronized( this )
190         {
191             if( m_count + count > m_maxCount )
192             {
193                 m_count = m_maxCount;
194             }
195             else
196             {
197                 m_count += count;
198             }
199             notifyAll();
200         }
201     }
202
203     /**
204      * Tries to acquire all the semaphores thus bringing the count to zero.
205      *
206      * @throws InterruptedException if the thread is interrupted when blocked on
207      * this call
208      * @see #acquire()
209      * @see #releaseAll()
210      */

211     public void acquireAll()
212         throws InterruptedException JavaDoc
213     {
214         synchronized( this )
215         {
216             for( int index = 0; index < m_maxCount; index++ )
217             {
218                 acquire();
219             }
220         }
221     }
222
223     /**
224      * Releases all semaphores setting the count to max count.
225      * Warning: If this method is called by a thread that did not make a
226      * corresponding acquireAll() call, then you better know what you are doing!
227      *
228      * @see #acquireAll()
229      */

230     public void releaseAll()
231     {
232         synchronized( this )
233         {
234             release( m_maxCount );
235             notifyAll();
236         }
237     }
238
239     /**
240      * This method blocks the calling thread until the count drops to zero.
241      * The method is not stateful and hence a drop to zero will not be recognized
242      * if a release happens before this call. You can use this method to implement
243      * threads that dynamically increase the resource pool or that log occurences
244      * of resource starvation. Also called a reverse-sensing semaphore.
245      *
246      * @throws InterruptedException if the thread is interrupted while waiting
247      */

248     public void starvationCheck()
249         throws InterruptedException JavaDoc
250     {
251         synchronized( m_starvationLock )
252         {
253             if( m_count != 0 )
254             {
255                 m_starvationLock.wait();
256             }
257         }
258     }
259 }
260
Popular Tags