Package ghidra.async

Class AsyncLazyMap<K,V>

java.lang.Object
ghidra.async.AsyncLazyMap<K,V>
Type Parameters:
K - the type of keys
V - the type of values

public class AsyncLazyMap<K,V> extends Object
A map of cached values computed upon the first request, asynchronously

Each key present in the cache behaves similarly to AsyncLazyValue. The cache starts empty. Whenever a key is requested, a computation for that key is started, but a future is immediately returned. If the computation succeeds, the completed future is cached indefinitely, and the result is recorded. Any subsequent requests for the same key return the same future, even if the computation for that key has not yet completed. Thus, when it completes, all requests for that key will be fulfilled by the result of the first request. If the computation completes exceptionally, the key is optionally removed from the cache. Thus, a subsequent request for a failed key may retry the computation.

Values can also be provided "out of band." That is, they may be provided by an alternative computation. This is accomplished using get(Object, Function), put(Object) or put(Object, Object). The last immediately provides a value and completes any outstanding requests, even if there was an active computation for the key. The first claims the key and promises to provide the value at a later time.

At any point, an unmodifiable view of the completed, cached values may be obtained.

  • Field Details

  • Constructor Details

    • AsyncLazyMap

      public AsyncLazyMap(Map<K,V> map, Function<K,CompletableFuture<V>> function)
      Construct a lazy map for the given function
      Parameters:
      map - the backing map. The lazy map ought to have an exclusive reference to this map. Mutations to the map outside of those caused by the lazy map may cause undefined behavior.
      function - specifies the computation, given a key
  • Method Details

    • putFuture

      protected void putFuture(K key, AsyncLazyMap.KeyedFuture<K,V> future)
    • forgetErrors

      public AsyncLazyMap<K,V> forgetErrors(BiPredicate<? super K,? super Throwable> predicate)
      Sets a predicate to determine which errors to forget (i.e., retry)

      A request resulting in an error that is remembered will not be retried until the cache is invalidated. For a forgotten error, the request is retried if re-requested later.

      This will replace the behavior of any previous error-testing predicate.

      Parameters:
      predicate - the predicate
      Returns:
      this lazy map
    • rememberErrors

      public AsyncLazyMap<K,V> rememberErrors(BiPredicate<? super K,? super Throwable> predicate)
      Sets a predicate to determine which errors to remember
      Parameters:
      predicate - the predicate
      Returns:
      this lazy map
      See Also:
    • forgetValues

      public AsyncLazyMap<K,V> forgetValues(BiPredicate<? super K,? super V> predicate)
      Sets a predicate to determine which values to forget

      The predicate is applied to a cached entry when its key is re-requested. If forgotten, the request will launch a fresh computation. The predicate is also applied at the time a computation is completed. An entry that is forgotten still completes normally; however, it never enters the cache, thus a subsequent request for the same key will launch a fresh computation.

      This will replace the behavior of any previous value-testing predicate.

      Parameters:
      predicate - the rule for forgetting entries
      Returns:
      this lazy map
    • rememberValues

      public AsyncLazyMap<K,V> rememberValues(BiPredicate<? super K,? super V> predicate)
      Sets a predicate to determine which values to remember
      Parameters:
      predicate - the rule for not forgetting entries
      Returns:
      this lazy map
      See Also:
    • get

      public AsyncLazyMap.KeyedFuture<K,V> get(K key, Function<K,CompletableFuture<V>> func)
      Request the value for a given key, using an alternative computation

      If this is called before any other get or put, the given function is launched for the given key. A CompletableFuture is returned immediately. Subsequent gets or puts on the same key will return the same future without starting any new computation.

      Parameters:
      key - the key
      func - an alternative computation function, given a key
      Returns:
      a future, possibly already completed, for the key's value
    • get

      public AsyncLazyMap.KeyedFuture<K,V> get(K key)
      Request the value for a given key

      If this is called before any other get or put, the computation given at construction is launched for the given key. A CompletableFuture is returned immediately. Subsequent calls gets or puts on the same key return the same future without starting any new computation.

      Parameters:
      key - the key
      Returns:
      a future, possible already completed, for the key's value
    • put

      public boolean put(K key, V value)
      Immediately provide an out-of-band value for a given key

      On occasion, the value for a key may become known outside of the specified computation. This method circumvents the function given during construction by providing the value for a key. If there is an outstanding request for the key's value -- a rare occasion -- it is completed immediately with the provided value. Calling this method for a key that has already completed has no effect.

      This is equivalent to the code map.put(k).complete(value), but atomic.

      Parameters:
      key - the key whose value to provide
      value - the provided value
      Returns:
      true if the key was completed by this call, false if the key had already been completed
    • put

      public AsyncLazyMap.KeyedFuture<K,V> put(K key)
      Provide an out-of-band value for a given key

      If this is called before get(Object), the computation given at construction is ignored for the given key. A new CompletableFuture is returned instead. The caller must see to this future's completion. Subsequent calls to either get(Object) or put(Object) on the same key return this same future without starting any computation.

      Under normal circumstances, the caller cannot determine whether or not it has "claimed" the computation for the key. If the usual computation is already running, then the computations are essentially in a race. As such, it is essential that alternative computations result in the same value for a given key as the usual computation. In other words, the functions must not differ, but the means of computation can differ. Otherwise, race conditions may arise.

      Parameters:
      key - the key whose value to provide
      Returns:
      a promise that the caller must fulfill or arrange to have fulfilled
    • forget

      public CompletableFuture<V> forget(K key)
      Remove a key from the map, without canceling any pending computation

      If the removed future has not yet completed, its value will never be added to the map of values. Subsequent gets or puts to the invalidated key will behave as if the key had never been requested.

      Parameters:
      key - the key to remove
      Returns:
      the invalidated future
    • remove

      public V remove(K key)
      Remove a key from the map, canceling any pending computation
      Parameters:
      key - the key to remove
      Returns:
      the previous value, if completed
    • getCompletedMap

      public Map<K,V> getCompletedMap()
      Get a view of completed keys with values

      The view is unmodifiable, but the backing map may still be modified as more keys are completed. Thus, access to the view ought to be synchronized on this lazy map.

      Returns:
      a map view of keys to values
    • getPendingKeySet

      public Set<K> getPendingKeySet()
      Get a copy of the keys which are requested but not completed

      This should only be used for diagnostics.

      Returns:
      a copy of the pending key set
    • clear

      public void clear()
      Clear the lazy map, including pending requests

      Pending requests will be cancelled

    • retainKeys

      public void retainKeys(Collection<K> keys)
      Retain only those entries whose keys appear in the given collection

      All removed entries with pending computations will be canceled

      Parameters:
      keys - the keys to retain
    • containsKey

      public boolean containsKey(K key)
      Check if a given key is in the map, pending or completed
      Parameters:
      key - the key to check
      Returns:
      true if present, false otherwise