2 * JCarder -- cards Java programs to keep threads disentangled
4 * Copyright (C) 2006-2007 Enea AB
5 * Copyright (C) 2007 Ulrik Svensson
6 * Copyright (C) 2007 Joel Rosdahl
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
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.
17 package com.enea.jcarder.analyzer;
21 import net.jcip.annotations.NotThreadSafe;
23 import com.enea.jcarder.common.LockingContext;
24 import com.enea.jcarder.common.contexts.ContextReaderIfc;
27 * A LockEdge instance represents a directed edge from a source LockNode to a
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;
39 LockEdge(LockNode source,
42 int sourceLockingContextId,
43 int targetLockingContextId) {
47 mSourceContextId = sourceLockingContextId;
48 mTargetContextId = targetLockingContextId;
49 mNumberOfDuplicates = 0;
52 void merge(LockEdge other) {
53 assert this.equals(other);
54 mNumberOfDuplicates += (other.mNumberOfDuplicates + 1);
57 long getDuplicates() {
58 return mNumberOfDuplicates;
61 boolean alike(LockEdge other, ContextReaderIfc reader) {
63 * TODO Some kind of cache to improve performance? Note that the context
64 * IDs are not declared final.
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);
80 public boolean equals(Object obj) {
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?
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) {
97 public int hashCode() {
98 // TODO Improve hashCode algorithm to improve performance?
99 return mTarget.getLockId() + mSource.getLockId();
102 LockNode getTarget() {
106 LockNode getSource() {
110 int getSourceLockingContextId() {
111 return mSourceContextId;
114 int getTargetLockingContextId() {
115 return mTargetContextId;
119 * Translate the source and target context ID according to a translation
122 void translateContextIds(Map<Integer, Integer> translation) {
123 final Integer newSourceId = translation.get(mSourceContextId);
124 if (newSourceId != null && newSourceId != mSourceContextId) {
125 mSourceContextId = newSourceId;
127 final Integer newTargetId = translation.get(mTargetContextId);
128 if (newTargetId != null && newSourceId != mTargetContextId) {
129 mTargetContextId = newTargetId;
137 public String toString() {
138 return " " + mSource + "->" + mTarget;