*** empty log message ***
[IRC.git] / Robust / Transactions / jcarderdstm2version / src / com / enea / jcarder / analyzer / LockNode.java
1 /*
2  * JCarder -- cards Java programs to keep threads disentangled
3  *
4  * Copyright (C) 2006-2007 Enea AB
5  * Copyright (C) 2007 Ulrik Svensson
6  * Copyright (C) 2007 Joel Rosdahl
7  *
8  * This program is made available under the GNU GPL version 2, with a special
9  * exception for linking with JUnit. See the accompanying file LICENSE.txt for
10  * details.
11  *
12  * This program is distributed in the hope that it will be useful, but WITHOUT
13  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14  * FITNESS FOR A PARTICULAR PURPOSE.
15  */
16
17 package com.enea.jcarder.analyzer;
18
19 import java.util.HashMap;
20 import java.util.Map;
21 import java.util.Set;
22
23 import net.jcip.annotations.NotThreadSafe;
24
25 import com.enea.jcarder.common.contexts.ContextReaderIfc;
26
27 /**
28  * A LockNode instance represents a lock in a graph.
29  */
30 @NotThreadSafe
31 class LockNode {
32     enum CycleType { NO_CYCLE, SINGLE_THREADED_CYCLE, CYCLE };
33
34     private final int mLockId;
35     private Map<LockEdge, LockEdge> mOutgoingEdges;
36     private CycleType mCycleType = CycleType.NO_CYCLE;
37
38     LockNode(final int lockId) {
39         mLockId = lockId;
40         mOutgoingEdges = new HashMap<LockEdge, LockEdge>();
41     }
42
43     int getLockId() {
44         return mLockId;
45     }
46
47     CycleType getCycleType() {
48         return mCycleType;
49     }
50
51     void raiseCycleType(CycleType newCycleType) {
52         if (newCycleType.compareTo(mCycleType) > 0) {
53             mCycleType = newCycleType;
54         }
55     }
56
57     void addOutgoingEdge(LockEdge newEdge) {
58         LockEdge existingEdge = mOutgoingEdges.get(newEdge);
59         if (existingEdge == null) {
60             mOutgoingEdges.put(newEdge, newEdge);
61         } else {
62             existingEdge.merge(newEdge);
63         }
64     }
65
66     void populateContextIdTranslationMap(Map<Integer, Integer> translationMap) {
67         for (LockEdge edge : mOutgoingEdges.values()) {
68             translationMap.put(edge.getSourceLockingContextId(),
69                                edge.getSourceLockingContextId());
70             translationMap.put(edge.getTargetLockingContextId(),
71                                edge.getTargetLockingContextId());
72         }
73     }
74
75     void translateContextIds(Map<Integer, Integer> translation) {
76         Map<LockEdge, LockEdge> oldEdges = mOutgoingEdges;
77         mOutgoingEdges = new HashMap<LockEdge, LockEdge>(oldEdges.size());
78         for (LockEdge edge : oldEdges.values()) {
79             edge.translateContextIds(translation);
80             addOutgoingEdge(edge);
81         }
82     }
83
84     Set<LockEdge> getOutgoingEdges() {
85         return mOutgoingEdges.keySet();
86     }
87
88     public String toString() {
89         return "L_" + mLockId;
90     }
91
92     long numberOfUniqueEdges() {
93         return mOutgoingEdges.size();
94     }
95
96     long numberOfDuplicatedEdges() {
97         long numberOfDuplicatedEdges = 0;
98         for (LockEdge edge : mOutgoingEdges.values()) {
99             numberOfDuplicatedEdges += edge.getDuplicates();
100         }
101         return numberOfDuplicatedEdges;
102     }
103
104     boolean alike(LockNode other, ContextReaderIfc reader) {
105         // TODO Maybe introduce some kind of cache to improve performance?
106         String thisClassName = reader.readLock(mLockId).getClassName();
107         String otherClassName = reader.readLock(other.mLockId).getClassName();
108         return thisClassName.equals(otherClassName);
109     }
110 }