KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jboss > ejb > plugins > lock > NonReentrantLock


1 /*
2 * JBoss, Home of Professional Open Source
3 * Copyright 2005, JBoss Inc., and individual contributors as indicated
4 * by the @authors tag. See the copyright.txt in the distribution for a
5 * full listing of individual contributors.
6 *
7 * This is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU Lesser General Public License as
9 * published by the Free Software Foundation; either version 2.1 of
10 * the License, or (at your option) any later version.
11 *
12 * This software is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this software; if not, write to the Free
19 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
20 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
21 */

22 package org.jboss.ejb.plugins.lock;
23
24 import org.jboss.util.deadlock.ApplicationDeadlockException;
25 import org.jboss.util.deadlock.Resource;
26 import org.jboss.util.deadlock.DeadlockDetector;
27
28 import javax.transaction.Transaction JavaDoc;
29
30 /**
31  * Implementents a non reentrant lock with deadlock detection
32  * <p/>
33  * It will throw a ReentranceException if the same thread tries to acquire twice
34  * or the same transaction tries to acquire twice
35  *
36  * @author <a HREF="bill@jboss.org">Bill Burke</a>
37  * @author <a HREF="alex@jboss.org">Alexey Loubyansky</a>
38  * @version $Revision: 37459 $
39  */

40 public class NonReentrantLock implements Resource
41 {
42    public static class ReentranceException extends Exception JavaDoc
43    {
44       public ReentranceException()
45       {
46       }
47
48       public ReentranceException(String JavaDoc message)
49       {
50          super(message);
51       }
52    }
53
54    //private static final Logger log = Logger.getLogger(NonReentrantLock.class);
55

56    protected Thread JavaDoc lockHolder;
57    protected Object JavaDoc lock = new Object JavaDoc();
58    protected volatile int held = 0;
59    protected Transaction JavaDoc holdingTx = null;
60    private boolean inNonReentrant;
61
62    public Object JavaDoc getResourceHolder()
63    {
64       if(holdingTx != null) return holdingTx;
65       return lockHolder;
66    }
67
68    protected boolean acquireNonReentrant(long waitTime, Transaction JavaDoc miTx)
69       throws ApplicationDeadlockException, InterruptedException JavaDoc, ReentranceException
70    {
71       synchronized(lock)
72       {
73          final Thread JavaDoc curThread = Thread.currentThread();
74          if(lockHolder != null)
75          {
76             if(lockHolder == curThread)
77             {
78                if(inNonReentrant)
79                {
80                   throw new ReentranceException("The same thread reentered: thread-holder=" +
81                      lockHolder +
82                      ", holding tx=" +
83                      holdingTx +
84                      ", current tx=" + miTx);
85                }
86             }
87             else if(miTx != null && miTx.equals(holdingTx))
88             {
89                if(inNonReentrant)
90                {
91                   throw new ReentranceException("The same tx reentered: tx=" +
92                      miTx +
93                      ", holding thread=" +
94                      lockHolder +
95                      ", current thread=" + curThread);
96                }
97             }
98             else
99             {
100                // Always upgrade deadlock holder to Tx so that we can detect lock properly
101
Object JavaDoc deadlocker = curThread;
102                if(miTx != null) deadlocker = miTx;
103                try
104                {
105                   DeadlockDetector.singleton.deadlockDetection(deadlocker, this);
106                   while(lockHolder != null)
107                   {
108                      if(waitTime < 1)
109                      {
110                         lock.wait();
111                      }
112                      else
113                      {
114                         lock.wait(waitTime);
115                      }
116                      // If we waited and never got lock, abort
117
if(waitTime > 0 && lockHolder != null) return false;
118                   }
119                }
120                finally
121                {
122                   DeadlockDetector.singleton.removeWaiting(deadlocker);
123                }
124             }
125          }
126
127          ++held;
128          lockHolder = curThread;
129          holdingTx = miTx;
130          inNonReentrant = true;
131       }
132       return true;
133    }
134
135    protected boolean acquireReentrant(long waitTime, Transaction JavaDoc miTx)
136       throws ApplicationDeadlockException, InterruptedException JavaDoc, ReentranceException
137    {
138       synchronized(lock)
139       {
140          final Thread JavaDoc curThread = Thread.currentThread();
141          if(lockHolder != null)
142          {
143             if(lockHolder != curThread && (miTx == null || miTx.equals(holdingTx)))
144             {
145                // Always upgrade deadlock holder to Tx so that we can detect lock properly
146
Object JavaDoc deadlocker = curThread;
147                if(miTx != null) deadlocker = miTx;
148                try
149                {
150                   DeadlockDetector.singleton.deadlockDetection(deadlocker, this);
151                   while(lockHolder != null)
152                   {
153                      if(waitTime < 1)
154                      {
155                         lock.wait();
156                      }
157                      else
158                      {
159                         lock.wait(waitTime);
160                      }
161                      // If we waited and never got lock, abort
162
if(waitTime > 0 && lockHolder != null) return false;
163                   }
164                }
165                finally
166                {
167                   DeadlockDetector.singleton.removeWaiting(deadlocker);
168                }
169             }
170          }
171
172          ++held;
173          lockHolder = curThread;
174          holdingTx = miTx;
175       }
176       return true;
177    }
178
179    public boolean attempt(long waitTime, Transaction JavaDoc miTx, boolean nonReentrant)
180       throws ApplicationDeadlockException, InterruptedException JavaDoc, ReentranceException
181    {
182       return nonReentrant ? acquireNonReentrant(waitTime, miTx) : acquireReentrant(waitTime, miTx);
183    }
184
185    public void release(boolean nonReentrant)
186    {
187       synchronized(lock)
188       {
189          held--;
190          if(held < 0)
191          {
192             throw new IllegalStateException JavaDoc("Released lock too many times");
193          }
194          else if(held == 0)
195          {
196             lockHolder = null;
197             holdingTx = null;
198             lock.notify();
199          }
200
201          if(nonReentrant)
202          {
203             inNonReentrant = false;
204          }
205       }
206    }
207 }
208
Popular Tags