01: /*
02: This source file is part of Smyle, a database library.
03: For up-to-date information, see http://www.drjava.de/smyle
04: Copyright (C) 2001 Stefan Reich (doc@drjava.de)
05:
06: This library is free software; you can redistribute it and/or
07: modify it under the terms of the GNU Lesser General Public
08: License as published by the Free Software Foundation; either
09: version 2.1 of the License, or (at your option) any later version.
10:
11: This library is distributed in the hope that it will be useful,
12: but WITHOUT ANY WARRANTY; without even the implied warranty of
13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14: Lesser General Public License for more details.
15:
16: You should have received a copy of the GNU Lesser General Public
17: License along with this library; if not, write to the Free Software
18: Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19:
20: For full license text, see doc/license/lgpl.txt in this distribution
21: */
22:
23: package drjava.util;
24:
25: import java.util.*;
26:
27: public class DeadlockDetector {
28: static/*Weak*/HashMap<Thread, ArrayList<Object>> locks = new /*Weak*/HashMap<Thread, ArrayList<Object>>();
29: static/*Weak*/HashMap<Object, HashSet<Object>> order = new /*Weak*/HashMap<Object, HashSet<Object>>();
30:
31: public static synchronized void clear() {
32: locks.clear();
33: }
34:
35: static void addToOrder(Object a, Object b) {
36: if (a == b)
37: return;
38: HashSet<Object> s = order.get(a);
39: if (s == null)
40: order.put(a, s = new HashSet<Object>());
41: s.add(b);
42: }
43:
44: public static synchronized void gettingMonitor(Thread thread,
45: Object object) {
46: ArrayList<Object> l = locks.get(thread);
47: if (l == null)
48: locks.put(thread, l = new ArrayList<Object>());
49:
50: for (int i = 0; i < l.size(); i++)
51: addToOrder(l.get(i), object);
52:
53: l.add(object);
54:
55: detectCycle(object);
56: }
57:
58: static void detectCycle(Object o) {
59: detectCycle(new HashSet<Object>(), o);
60: }
61:
62: static void detectCycle(HashSet<Object> s, Object o) {
63: if (s.contains(o))
64: throw new Error("Deadlock detected!");
65: s.add(o);
66: HashSet<Object> hs = order.get(o);
67: if (hs != null)
68: for (Iterator<Object> i = hs.iterator(); i.hasNext();)
69: detectCycle(s, i.next());
70: }
71:
72: public static synchronized void releasingMonitor(Thread thread,
73: Object object) {
74: ArrayList<Object> l = locks.get(thread);
75: if (l == null)
76: throw new Error("release before get");
77: if (l.get(l.size() - 1) != object)
78: throw new Error("Bad get/release order");
79: l.remove(l.size() - 1);
80: if (l.isEmpty())
81: locks.remove(thread);
82: }
83: }
|