Package: org.apache.groovy.runtime.indy

## [Java] Class SwitchPointInvalidator

- org.apache.groovy.runtime.indy.SwitchPointInvalidator

-     public final class SwitchPointInvalidator
      extends Object

  Lazily allocates a SwitchPoint and retires it on demand.

  Call sites install the switch point returned by getSwitchPoint() in `guardWithTest` chains. invalidate() retires the live switch point so linked sites fall back and re-link; the next getSwitchPoint() allocates a fresh one.

  Bulk paths (category enter/leave, custom MetaClass events) should prefer detachLive() and a single SwitchPoint.invalidateAll over many individual invalidate() calls.

  There is no permanent failover: stock invalidation is scoped to a single class, so deopt storms from a process-wide SwitchPoint do not apply and a simple replace-on-invalidate model is sufficient.

  A process-wide registry tracks every live SwitchPoint so bulk retirement is O(live domains), and is skipped entirely while the registry is empty — e.g. classic-only bytecode never links an indy MOP guard. Registration precedes publication, so an empty (or entry-less) observation proves no guard chain holds a live SwitchPoint that the observer could have needed to retire.

  Registry entries hold their invalidator strongly; the invalidator's owner is responsible for retiring the domain when it is discarded (see the reclaim anchor on `ClassInfo`'s class-level domain), which is what removes the entry. A guard chain keeps only the SwitchPoint's internal invoker alive, not the SwitchPoint object, so the registry entry is what keeps a still-installed guard retirable until its domain is explicitly retired.

  ## Layering

  This is the mechanism half of the MOP invalidation subsystem and makes no policy decisions. It has exactly two supported consumers: ClassInfo, which owns domain instances (allocation, local invalidate, detach), and IndyInvalidation, which owns invalidation width policy, reclaim anchoring and per-Class domain continuity. On its own this class guarantees only the single-domain lifecycle documented above (single-use SwitchPoints; registration precedes publication); guarantees about domain identity across ClassInfo recreation exist only under IndyInvalidation's management. It is not an extension point and may change incompatibly.
  Since:
    6.0.0

- - ### Constructor Summary

    Constructors
    Constructor and description
    `SwitchPointInvalidator()` Creates an invalidator with no live SwitchPoint until the first getSwitchPoint() call.

  - ### Methods Summary

    Methods
    Type Params | Return Type | Name and description
    --- | --- | ---
    `` | `public SwitchPoint` | `detachLive()` Atomically detaches the live switch point for bulk SwitchPoint.invalidateAll without invalidating it yet.
    `` | `public int` | `getRetirementCount()` Returns how many live switch points have been retired.
    `` | `public SwitchPoint` | `getSwitchPoint()` Returns a live switch point to install in a call-site guard chain.
    `` | `public void` | `invalidate()` Invalidates the current live switch point (if any) so linked sites re-link.
    `` | `public static void` | `invalidateIfLive(SwitchPoint sp)` Invalidates `sp` when non-null and still valid.
    `` | `public void` | `setReclaimAnchor(Object anchor)` Parks `anchor` so it stays strongly reachable while this invalidator is reachable.

  - ### Inherited Methods Summary

    Inherited Methods
    Methods inherited from class | Name
    --- | ---
    `class Object` | `equals, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait`

- - ### Constructor Detail

    - #### public SwitchPointInvalidator()

      Creates an invalidator with no live SwitchPoint until the first getSwitchPoint() call. Field initializers own all state.

  - ### Method Detail

    - #### public SwitchPoint detachLive()

      Atomically detaches the live switch point for bulk SwitchPoint.invalidateAll without invalidating it yet. The caller must invalidate any non-null return value.

      Returns:
        the detached live switch point, or `null` if none was live

    - #### public int getRetirementCount()

      Returns how many live switch points have been retired.

      Returns:
        the retirement count

    - #### public SwitchPoint getSwitchPoint()

      Returns a live switch point to install in a call-site guard chain. Lazily allocates on first use after construction or after retirement.

      Returns:
        a live switch point (never `null`)

    - #### public void invalidate()

      Invalidates the current live switch point (if any) so linked sites re-link. A subsequent getSwitchPoint() allocates a fresh switch point.

    - #### public static void invalidateIfLive(SwitchPoint sp)

      Invalidates `sp` when non-null and still valid.

      Parameters:
        `sp` - candidate switch point (may be `null`)

    - #### public void setReclaimAnchor(Object anchor)

      Parks `anchor` so it stays strongly reachable while this invalidator is reachable. See reclaimAnchor.

      Parameters:
        `anchor` - the object to keep reachable (may be `null` to clear)