Class SwitchPointCache.Builder<T>

java.lang.Object
org.postgresql.pljava.internal.SwitchPointCache.Builder<T>
Enclosing class:
SwitchPointCache

public static class SwitchPointCache.Builder<T> extends Object
Builder for use during the static initialization of a class that uses SwitchPointCache.

The builder's constructor is passed information about the class, and about a SwitchPoint that will be used when the dependent values need to be invalidated. To accommodate invalidation schemes with different granularity, the SwitchPoint used may be kept in an instance field of the class, or in a static field and governing all instances of the class, or even somewhere else entirely and used for widespread or global invalidation.

The builder's withDependent method is then used to declare each value that can be computed and cached in an instance of the class, by giving the name of a static method that computes the value (given one argument, an instance of the class) and functions to get and set a MethodHandle-typed per-instance slot where the computation result will be cached.

Finally, the builder's build method returns a Consumer<T> that can be saved in a static final field and invoked in the object's constructor; it will initialize all of the new instance's fields that were declared in withDependent calls to their initial, uncomputed states.

  • Constructor Details

    • Builder

      public Builder(Class<T> c)
      Create a builder that will be used to declare dependent values controlled by a single SwitchPoint and to create an initializer for the per-instance slots that will hold their states.
      Parameters:
      c - the class being configured by this Builder
  • Method Details

    • withDescriber

      public SwitchPointCache.Builder<T> withDescriber(Function<? super T,String> describer)
      Parameters:
      describer - function, with a signature like that of Object.toString, that will produce a useful description of the object if needed in an exception message. The default if this method is not called is Object::toString; a different describer can be supplied if the output of toString isn't well suited for an exception message. If null, any exception will have its bare constant message with nothing added about the specific receiver object.
    • withLookup

      Supply the Lookup object to be used in resolving dependent methods.
      Parameters:
      l - a Lookup object obtained by the caller and able to introspect in the class
    • withCandidates

      public SwitchPointCache.Builder<T> withCandidates(Method[] ms)
      Supply the candidate methods to be available to subsequent withDependent calls.
      Parameters:
      ms - array of methods such as the caller may obtain with getDeclaredMethods, avoiding the access complications of having this class do it. The methods will be filtered to only those that are static with a non-void return type and exactly one parameter, assignable from the target class, and uniquely named within that set. Only such methods can be named in later withDependent calls. No reference to the array will be retained.
    • withSwitchPoint

      public SwitchPointCache.Builder<T> withSwitchPoint(Function<T,SwitchPoint> spGetter)
      Supply a function mapping a receiver object instance to the SwitchPoint to be associated with subsequently declared slots.
      Parameters:
      spGetter - a function usable to fetch the SwitchPoint that controls this cache. It is passed an instance of T but need not use it (in the case, for example, of a single controlling SwitchPoint held in a static).
    • withSlots

      public SwitchPointCache.Builder<T> withSlots(Function<T,MethodHandle[]> slotGetter)
      Supply a function mapping a receiver object instance to the per-instance MethodHandle array whose elements will be the slots.
      Parameters:
      slotGetter - a function usable to fetch the slot array for an instance.
    • withReturnType

      public SwitchPointCache.Builder<T> withReturnType(Class<?> t)
      Adjust the static return type of subsequently declared dependents that return references.

      This can be a more compact notation if compute methods or API methods from a superclass or subclass will be reused and the return type needs to be adjusted to match the static type in the API method (possibly erased from a generic type).

      Parameters:
      t - Class to serve as the following dependents' static return type. Pass null to discontinue adjusting return types for following dependents.
      Throws:
      IllegalArgumentException - if t represents a primitive type.
    • withReceiverType

      public SwitchPointCache.Builder<T> withReceiverType(Class<?> t)
      Adjust the static receiver type of subsequently declared dependents.

      This can be a more compact notation if compute methods or API methods from a superclass or subclass will be reused and the receiver type needs to be adjusted to match the static type in the API method (possibly erased from a generic type).

      Parameters:
      t - Class to serve as the following dependents' static receiver type. Pass null to discontinue adjusting receiver types for following dependents.
      Throws:
      IllegalArgumentException - if t is neither a widening nor a narrowing of the receiver type specified for this builder.
    • build

      public UnaryOperator<MethodHandle[]> build()
      Return a UnaryOperator<MethodHandle[]> to be invoked in the constructor of a client object, applied to a newly-allocated array of the right number of slots, which will initialize all of the array's elements with the corresponding fallback method handles and return the initialized array.

      The initializer can be used conveniently in a constructor that assigns the array to a final field, or calls a superclass constructor that does so, to arrange that the array's elements are written in advance of Java's freeze of the final array reference field.

    • withDependent

      public SwitchPointCache.Builder<T> withDependent(String methodName, int index)
      Declare one dependent item that will be controlled by this builder's SwitchPoint.

      An item is declared by naming the static method that can compute its value when needed, and the index into the per-instance MethodHandle[] "slots" array that will be used to cache the value. Typically, these will be private, and there will be an API method for retrieving the value, by fetching the method handle from the array index given here, and invoking it.

      The method handle that will be found in the named slot has a return type matching the compute method named here, and two parameters; it expects the receiver object as the first parameter, and itself as the second. So the typical API method is simply:

       MethodHandle h = slots[MY_SLOT];
       return (cast)h.invokeExact(this, h);
      

      When there is a cached value and the SwitchPoint has not been invalidated, the two arguments are ignored and the cached value is returned.

      Parameters:
      methodName - name of the static method that will be used to compute values for this item. It must be found among the methods that were passed to the Builder constructor, only considering those that are static, with a non-void return and one argument of the class type.
      index - index into the per-instance slot arrray where the cached state will be maintained.