Programmers are often confused by the results of asynchronous executions because they can not foresee all possible interleavings of events. In fact, most of these interleavings are irrelevant: the programmer does not care about the arbitrary orderings of events by physical time. Instead, the programmer is concerned with the logical ordering of events. At the primitive event level, this ordering is captured by Lamport's happened before relation. Other debuggers have used temporal logic to express assertions about happened before [5,10] but they do not use behavioral abstraction. We extend the relation to abstract events, defining three relations: precedes, parallels, and overlaps [15]. Informally, if A and B are abstract events, then
precedes
(denoted
) iff
there is some dependency from an event in A to an event in B but
no dependency from an event in B to an event in A,
parallels
(denoted A||B) iff there is no
dependency from an event in A to an event in B and no dependency
from an event in B to an event in A, and
overlaps
(denoted
) iff
there is both a dependency from an event in A to an event in B and
a dependency from an event in B to an event in A.