- Type Parameters:
T
- the extent local's type
An extent-local variable (hereinafter called an extent local) differs from a normal variable in that it is dynamically
scoped and intended for cases where context needs to be passed from a caller
to a transitive callee without using an explicit parameter. An extent-local variable
does not have a default/initial value: it is bound, meaning it gets a value,
when executing an operation specified to where(ExtentLocal, Object)
.
Code executed by the operation
uses the get()
method to get the value of the extent local. The extent local reverts
to being unbound (or its previous value) when the operation completes.
Access to the value of an extent local is controlled by the accessibility
of the ExtentLocal
object. A ExtentLocal
object will typically be declared
in a private static field so that it can only be accessed by code in that class
(or other classes within its nest).
Extent locals support nested bindings. If an extent local has a value
then the runWithBinding
or callWithBinding
can be invoked to run
another operation with a new value. Code executed by this methods "sees" the new
value of the extent local. The extent local reverts to its previous value when the
operation completes.
Unless otherwise specified, passing a null
argument to a constructor
or method in this class will cause a NullPointerException
to be thrown.
- API Note:
- The following example uses an extent local to make credentials available to callees.
private static final ExtentLocal<Credentials> CREDENTIALS = ExtentLocal.newInstance(); Credentials creds = ... ExtentLocal.where(CREDENTIALS, creds).run(() -> { : Connection connection = connectDatabase(); : }); Connection connectDatabase() { Credentials credentials = CREDENTIALS.get(); : }
- Implementation Note:
- Extent locals are designed to be used in fairly small numbers.
get()
initially performs a linear search through enclosing scopes to find a extent local's innermost binding. It then caches the result of the search in a small thread-local cache. Subsequent invocations ofget()
for that extent local will almost always be very fast. However, if a program has many extent locals that it uses cyclically, the cache hit rate will be low and performance will be poor. On the other hand, this design allows extent-local inheritance byStructuredTaskScope
threads to be very fast: in essence, no more than copying a pointer, and leaving a extent-local binding also requires little more than updating a pointer. Because the extent-local per-thread cache is small, you should try to minimize the number of bound extent locals in use. For example, if you need to pass a number of values as extent locals, it makes sense to create a record class to hold those values, and then bind a single extent local to an instance of that record. - Since:
- 19
-
Nested Class Summary
Nested ClassesModifier and TypeClassDescriptionstatic final class
An immutable map from a set of ExtentLocals to their bound values. -
Method Summary
Modifier and TypeMethodDescriptionget()
Returns the value of the extent local.final int
hashCode()
Returns a hash code value for the object.boolean
isBound()
Returnstrue
if the extent local is bound to a value.static <T> ExtentLocal<T>
Creates an extent-local handle to refer to a value of type T.Return the value of the extent local if bound, otherwise returnsother
.orElseThrow
(Supplier<? extends X> exceptionSupplier) Return the value of the extent local if bound, otherwise throw an exception produced by the exception supplying function.static <T> ExtentLocal.Carrier
where
(ExtentLocal<T> key, T value) Create a binding for an ExtentLocal instance.static <T> void
where
(ExtentLocal<T> key, T value, Runnable op) Creates a binding for an ExtentLocal instance and runs an operation with that bound ExtentLocal.static <T,
U> U where
(ExtentLocal<T> key, T value, Callable<U> op) Creates a binding for an ExtentLocal instance and runs a value-returning operation with that bound ExtentLocal.
-
Method Details
-
hashCode
public final int hashCode()Description copied from class:Object
Returns a hash code value for the object. This method is supported for the benefit of hash tables such as those provided byHashMap
.The general contract of
hashCode
is:- Whenever it is invoked on the same object more than once during
an execution of a Java application, the
hashCode
method must consistently return the same integer, provided no information used inequals
comparisons on the object is modified. This integer need not remain consistent from one execution of an application to another execution of the same application. - If two objects are equal according to the
equals
method, then calling thehashCode
method on each of the two objects must produce the same integer result. - It is not required that if two objects are unequal
according to the
equals
method, then calling thehashCode
method on each of the two objects must produce distinct integer results. However, the programmer should be aware that producing distinct integer results for unequal objects may improve the performance of hash tables.
- Whenever it is invoked on the same object more than once during
an execution of a Java application, the
-
where
Create a binding for an ExtentLocal instance. ThatExtentLocal.Carrier
may be used later to invoke aCallable
orRunnable
instance. More bindings may be added to theExtentLocal.Carrier
by theExtentLocal.Carrier.where(ExtentLocal, Object)
method.- Type Parameters:
T
- the type of the ExtentLocal- Parameters:
key
- the ExtentLocal to bindvalue
- The value to bind it to- Returns:
- A Carrier instance that contains one binding, that of key and value
-
where
Creates a binding for an ExtentLocal instance and runs a value-returning operation with that bound ExtentLocal.- Type Parameters:
T
- the type of the ExtentLocalU
- the type of the Result- Parameters:
key
- the ExtentLocal to bindvalue
- The value to bind it toop
- the operation to call- Returns:
- the result
- Throws:
Exception
- if the operation completes with an exception
-
where
Creates a binding for an ExtentLocal instance and runs an operation with that bound ExtentLocal.- Type Parameters:
T
- the type of the ExtentLocal- Parameters:
key
- the ExtentLocal to bindvalue
- The value to bind it toop
- the operation to run
-
newInstance
Creates an extent-local handle to refer to a value of type T.- Type Parameters:
T
- the type of the extent local's value.- Returns:
- a extent-local handle
-
get
Returns the value of the extent local.- Returns:
- the value of the extent local
- Throws:
NoSuchElementException
- if the extent local is not bound (exception is TBD)
-
isBound
public boolean isBound()Returnstrue
if the extent local is bound to a value.- Returns:
true
if the extent local is bound to a value, otherwisefalse
-
orElse
Return the value of the extent local if bound, otherwise returnsother
.- Parameters:
other
- the value to return if not bound, can benull
- Returns:
- the value of the extent local if bound, otherwise
other
-
orElseThrow
Return the value of the extent local if bound, otherwise throw an exception produced by the exception supplying function.- Type Parameters:
X
- Type of the exception to be thrown- Parameters:
exceptionSupplier
- the supplying function that produces an exception to be thrown- Returns:
- the value of the extent local if bound
- Throws:
X
- if the extent local is unbound
-