Interface SimpleChunkVisitor

  • All Known Implementing Classes:
    StandardChunkVisitor

    public interface SimpleChunkVisitor
    This visitor's callbacks are invoked as we walk through a pipeline flow graph, and it splits it into chunks.

    A ForkScanner.visitSimpleChunks(SimpleChunkVisitor, ChunkFinder) creates these FlowChunks using a ChunkFinder to define the chunk boundaries.

    We walk through the FlowNodes in reverse order from end to start, so end callbacks are invoked before their corresponding start callbacks.

    Callback types

    There are two kinds of callbacks - chunk callbacks, and parallel structure callbacks.

    Chunk Callbacks:

    Chunk callback rules:

    1. For a single node, it may have EITHER OR BOTH chunkStart and chunkEnd events
    2. Every node that doesn't get a startChunk/endChunk callback gets an atomNode callback.
    3. For ChunkFinder implementations that match the BlockStartNode and BlockEndNode should never have both for a single node.
    4. You cannot have multiple of any of the same specific type of callbacks for the same flownode
    5. You cannot have a atomNode callback AND a start/end for the same flownode (application of the above).

    Parallel Structure Callbacks: Zero, One, or (in niche cases) several different ones may be invoked for any given FlowNode.

    These are used to provide awareness of parallel/branching structures if they need special handling.

    The cases where a node triggers multiple callbacks are where it is one of several forked branches of an incomplete parallel block. In this case it can be a parallelBranchEnd, also potentially a parallelEnd, plus whatever role that node might normally have (such as the start of another parallel).

    Implementations get to decide how to use and handle chunks, and should be stateful.

    At a minimum they should handle:

    • Cases where there is no enclosing chunk (no start/end found, or outside a chunk)
    • Cases where there is no chunk end to match the start, because we haven't finished running a block
    • Nesting of chunks
    Author:
    Sam Van Oort
    • Method Detail

      • chunkStart

        void chunkStart​(@NonNull
                        FlowNode startNode,
                        @CheckForNull
                        FlowNode beforeBlock,
                        @NonNull
                        ForkScanner scanner)
        Called when hitting the start of a chunk.
        Parameters:
        startNode - First node in chunk (marker), included in node
        beforeBlock - First node before chunk (null if none exist)
        scanner - Forkscanner used (for state tracking)
      • chunkEnd

        void chunkEnd​(@NonNull
                      FlowNode endNode,
                      @CheckForNull
                      FlowNode afterChunk,
                      @NonNull
                      ForkScanner scanner)
        Called when hitting the end of a chunk.
        Parameters:
        endNode - Last node in chunk
        afterChunk - Node after chunk (null if we are on the last node)
        scanner - Forkscanner used (for state tracking)
      • parallelStart

        void parallelStart​(@NonNull
                           FlowNode parallelStartNode,
                           @NonNull
                           FlowNode branchNode,
                           @NonNull
                           ForkScanner scanner)
        Notifies that we've hit the start of a parallel block (the point where it branches out).
        Parameters:
        parallelStartNode - The BlockStartNode beginning it, next will be branches
        branchNode - BlockStartNode for one of the branches (it will be labelled)
        scanner - ForkScanner used
      • parallelEnd

        void parallelEnd​(@NonNull
                         FlowNode parallelStartNode,
                         @NonNull
                         FlowNode parallelEndNode,
                         @NonNull
                         ForkScanner scanner)
        Notifies that we've seen the end of a parallel block
        Parameters:
        parallelStartNode - First node of parallel (BlockStartNode before the branches)
        parallelEndNode - Last node of parallel (BlockEndNode)
        scanner - ForkScanner used
      • parallelBranchStart

        void parallelBranchStart​(@NonNull
                                 FlowNode parallelStartNode,
                                 @NonNull
                                 FlowNode branchStartNode,
                                 @NonNull
                                 ForkScanner scanner)
        Hit the start of a parallel branch
        Parameters:
        parallelStartNode - First node of parallel (BlockStartNode before the branches)
        branchStartNode - BlockStartNode beginning the branch (this will have the ThreadNameAction giving its name)
        scanner - ForkScanner used
      • parallelBranchEnd

        void parallelBranchEnd​(@NonNull
                               FlowNode parallelStartNode,
                               @NonNull
                               FlowNode branchEndNode,
                               @NonNull
                               ForkScanner scanner)
        Hit the end start of a parallel branch

        May not be invoked if we're inside an in-progress parallel

        Parameters:
        parallelStartNode - First node of parallel (BlockStartNode before the branches)
        branchEndNode - Final node of the branch (may be BlockEndNode if done, otherwise just the last one executed)
        scanner - ForkScanner used
      • atomNode

        void atomNode​(@CheckForNull
                      FlowNode before,
                      @NonNull
                      FlowNode atomNode,
                      @CheckForNull
                      FlowNode after,
                      @NonNull
                      ForkScanner scan)
        Called for a flownode neither start nor end. Ways you may want to use this: accumulate pause time, collect errors, etc. Note: invocations don't guarantee whether or not you're within a marked chunk.
        Parameters:
        before - Node before the current
        atomNode - The node itself
        after - Node after the current
        scan - Reference to our forkscanner, if we want to poke at the state within