Class LockPrecedenceGraph
- All Implemented Interfaces:
Serializable
Nodes are lock-identity stableId strings (the same FK form used
elsewhere in LockAnalysis). Edges record an observed
"lockA held when lockB acquired" relationship — i.e. an enter() site on
lockB nested inside a MutexKey body protecting lockA. Each edge carries
the source location of the inner enter() so cycle diagnostics can point
users at the contributing call sites.
Deadlock model: a single nested-different-lock pair
(e.g. lockA → lockB with no opposing acquisition anywhere in
the program) is safe — there's no acquisition order that another
thread could violate. The deadlock condition requires a cycle:
lockA → lockB from one call site PLUS lockB → lockA
(directly or transitively) from another. The compiler fires
E08252 on edges that participate in a strongly-connected
component of size ≥ 2 (i.e. real cycles).
Self-loops (lockA → lockA) are not recorded: the same
lock reentrant on the same thread is legal (Java's ReentrantLock
semantics). The cross-thread variant (same lock across a thread
boundary) is handled separately by the C.3 verdict via E08253.
Thread-safety: same model as LockAnalysis — concurrent collection
during parallel listener walks, single-threaded consumption afterwards.
Uses ConcurrentHashMap for the adjacency map.
- See Also:
-
Nested Class Summary
Nested ClassesModifier and TypeClassDescriptionstatic final recordOne observed nested-enter relationship between two distinct lock identities. -
Constructor Summary
Constructors -
Method Summary
Modifier and TypeMethodDescriptionintAll edges leaving the given node (empty if none).edgesInCycle(Set<String> cycle) Edges of the graph whose endpoints both lie in the given cycle — these are the edges that participate in the deadlock-capable acquisition pattern.Find all strongly-connected components of size ≥ 2 in the graph.nodes()All node FQNs appearing as either source or target of any edge.voidrecordEdge(String outerLockId, String innerLockId, IToken innerCallLocation, String outerSiteId) Record an observed precedence "outer held → inner acquired." Self-loops (outer == inner) are silently ignored — reentrancy on the same thread is legal.
-
Constructor Details
-
LockPrecedenceGraph
public LockPrecedenceGraph()
-
-
Method Details
-
recordEdge
-
edgesFrom
All edges leaving the given node (empty if none). -
nodes
-
edgeCount
public int edgeCount() -
findCycles
Find all strongly-connected components of size ≥ 2 in the graph. Each non-trivial SCC corresponds to a deadlock-capable cycle: within the SCC every node reaches every other, meaning the acquisition-order constraints conflict.Uses Tarjan's SCC algorithm — O(V + E), single pass.
- Returns:
- list of SCCs as sets of lock identity stableIds. Only non-trivial SCCs (size ≥ 2) are returned; singleton SCCs are omitted (no cycle, no deadlock).
-
edgesInCycle
Edges of the graph whose endpoints both lie in the given cycle — these are the edges that participate in the deadlock-capable acquisition pattern. Used by C.3 to fireE08252at each participating inner enter() site with a message linking to the other edges.
-