*** empty log message ***
[IRC.git] / Robust / Transactions / jcarderdstm2version / src / com / enea / jcarder / analyzer / LockEdge.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.Map;
20
21 import net.jcip.annotations.NotThreadSafe;
22
23 import com.enea.jcarder.common.LockingContext;
24 import com.enea.jcarder.common.contexts.ContextReaderIfc;
25
26 /**
27  * A LockEdge instance represents a directed edge from a source LockNode to a
28  * target LockNode.
29  */
30 @NotThreadSafe
31 class LockEdge {
32     private final LockNode mSource;
33     private final LockNode mTarget;
34     private final long mThreadId; // The thread that did the synchronization.
35     private int mSourceContextId;
36     private int mTargetContextId;
37     private long mNumberOfDuplicates;
38
39     LockEdge(LockNode source,
40              LockNode target,
41              long threadId,
42              int sourceLockingContextId,
43              int targetLockingContextId) {
44         mSource = source;
45         mTarget = target;
46         mThreadId = threadId;
47         mSourceContextId = sourceLockingContextId;
48         mTargetContextId = targetLockingContextId;
49         mNumberOfDuplicates = 0;
50     }
51
52     void merge(LockEdge other) {
53         assert this.equals(other);
54         mNumberOfDuplicates += (other.mNumberOfDuplicates + 1);
55     }
56
57     long getDuplicates() {
58         return mNumberOfDuplicates;
59     }
60
61     boolean alike(LockEdge other, ContextReaderIfc reader) {
62         /*
63          * TODO Some kind of cache to improve performance? Note that the context
64          * IDs are not declared final.
65          */
66         LockingContext thisSourceContext =
67             reader.readContext(mSourceContextId);
68         LockingContext otherSourceContext =
69             reader.readContext(other.mSourceContextId);
70         LockingContext thisTargetContext =
71             reader.readContext(mTargetContextId);
72         LockingContext otherTargetContext =
73             reader.readContext(other.mTargetContextId);
74         return thisSourceContext.alike(otherSourceContext)
75                && thisTargetContext.alike(otherTargetContext)
76                && mSource.alike(other.mSource, reader)
77                && mTarget.alike(other.mTarget, reader);
78     }
79
80     public boolean equals(Object obj) {
81         /*
82          * TODO It might be a potential problem to use LockEdges in HashMaps
83          * since they are mutable and this equals method depends on them?
84          */
85         try {
86             LockEdge other = (LockEdge) obj;
87             return (mTarget.getLockId() == other.mTarget.getLockId())
88             && (mSource.getLockId() == other.mSource.getLockId())
89             && (mThreadId == other.mThreadId)
90             && (mSourceContextId == other.mSourceContextId)
91             && (mTargetContextId == other.mTargetContextId);
92         } catch (Exception e) {
93             return false;
94         }
95     }
96
97     public int hashCode() {
98         // TODO Improve hashCode algorithm to improve performance?
99         return mTarget.getLockId() + mSource.getLockId();
100     }
101
102     LockNode getTarget() {
103         return mTarget;
104     }
105
106     LockNode getSource() {
107         return mSource;
108     }
109
110     int getSourceLockingContextId() {
111         return mSourceContextId;
112     }
113
114     int getTargetLockingContextId() {
115         return mTargetContextId;
116     }
117
118     /**
119      * Translate the source and target context ID according to a translation
120      * map.
121      */
122     void translateContextIds(Map<Integer, Integer> translation) {
123         final Integer newSourceId = translation.get(mSourceContextId);
124         if (newSourceId != null && newSourceId != mSourceContextId) {
125             mSourceContextId = newSourceId;
126         }
127         final Integer newTargetId = translation.get(mTargetContextId);
128         if (newTargetId != null && newSourceId != mTargetContextId) {
129             mTargetContextId = newTargetId;
130         }
131     }
132
133     long getThreadId() {
134         return mThreadId;
135     }
136
137     public String toString() {
138         return "  " + mSource + "->" + mTarget;
139     }
140 }