GP-1545: De-guava the Debugger

This commit is contained in:
Dan 2023-02-27 12:26:21 -05:00
parent a2ae1f08ce
commit d43b9ead66
142 changed files with 1125 additions and 1889 deletions

View file

@ -17,14 +17,12 @@ package ghidra.async;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;
import com.google.common.cache.*;
/**
* A cache of futures which pairs each to its result by key
*
* <p>
* The cache accepts promises and results, storing unpaired entries for a timeout period. Each
* promise is fulfilled when the cache accepts its corresponding result, determined by key.
* Conversely, a cached result fulfills its corresponding promise, determined by key, when the cache
@ -32,6 +30,7 @@ import com.google.common.cache.*;
* given key enter the cache, they are paired, the promise is fulfilled, and both are removed from
* the cache.
*
* <p>
* If an entry is not paired within the timeout period, it is evicted. An evicted promise is likely
* a recoverable error, e.g., a request timed out. An evicted result is likely a logic or
* synchronization error. Requests, i.e., promises, are usually created before the result is
@ -53,66 +52,26 @@ public abstract class AsyncPairingCache<K, V> {
/**
* Construct a new matching cache
*
* @param concurrencyLevel the maximum number of thread expected to simultaneously access the
* cache
* @param timeoutMillis the amount of time (in milliseconds) a promise or result may pend before
* eviction
* @param maxPending the maximum number of pending promises or results before the eldest is
* evicted. Each is counted independently, e.g., a value of 5 permits 5 pending
* promises and 5 pending results simultaneously.
*/
public AsyncPairingCache(int concurrencyLevel, int timeoutMillis, int maxPending) {
results = CacheBuilder.newBuilder()
.concurrencyLevel(concurrencyLevel)
.expireAfterWrite(timeoutMillis, TimeUnit.MILLISECONDS)
.maximumSize(maxPending)
.removalListener(this::resultRemoved)
.build()
.asMap();
public AsyncPairingCache(int maxPending) {
results = createResultCache(maxPending);
resultsView = Collections.unmodifiableMap(results);
promises = CacheBuilder.newBuilder()
.concurrencyLevel(concurrencyLevel)
.expireAfterWrite(timeoutMillis, TimeUnit.MILLISECONDS)
.maximumSize(maxPending)
.removalListener(this::promiseRemoved)
.build()
.asMap();
promises = createPromiseCache(maxPending);
promisesView = Collections.unmodifiableMap(promises);
}
/**
* Called when a result is removed
*
* Eviction is likely due to a logic bug or a gratuitous result from an external source.
*
* @param rn the removal notification for the result entry
*/
protected abstract void resultRemoved(RemovalNotification<K, V> rn);
protected abstract Map<K, V> createResultCache(int max);
/**
* Called when a promise is removed
*
* The most common implementation is to complete the future exceptionally. The default
* implementation completes the future with a {@link RuntimeException}. Extensions should
* override this method. Note that this method is called for removal as a result of normal
* completion, too. In that case {@link RemovalNotification#getCause()} will return
* {@link RemovalCause#EXPLICIT}.
*
* @param rn the removal notification for the promise entry
*/
protected void promiseRemoved(RemovalNotification<K, CompletableFuture<V>> rn) {
if (rn.getCause() != RemovalCause.EXPLICIT) {
rn.getValue()
.completeExceptionally(new RuntimeException(
"Promise with key " + rn.getKey() +
" was evicted with the default handler"));
}
}
protected abstract Map<K, CompletableFuture<V>> createPromiseCache(int max);
/**
* Enter a promise for the the given key into the cache
*
* <p>
* If the result for the given key is already available, the promise does not enter the cache.
* Instead, the result is removed and the promise is completed.
*
@ -126,6 +85,7 @@ public abstract class AsyncPairingCache<K, V> {
/**
* Enter a promise for the the given key into the cache
*
* <p>
* If the result for the given key is already available, the promise does not enter the cache.
* Instead, the result is removed and the promise is completed.
*
@ -148,6 +108,7 @@ public abstract class AsyncPairingCache<K, V> {
/**
* Enter a result for the given key into the cache
*
* <p>
* If a promise for the key already exists, the result does not enter the cache. Instead, the
* promise is removed and completed.
*
@ -169,11 +130,8 @@ public abstract class AsyncPairingCache<K, V> {
/**
* Flush the cache, completing all pending requests exceptionally
*
* Both sides of the cache are cleared. Note that this will invoke the removal callback for each
* entry giving {@link RemovalCause#EXPLICIT} as the cause. For requests, the callback ought not
* to complete the request, exceptionally or otherwise, since the flush is about to complete it
* with the given exception. The implementor may freely choose how to handle flushed pending
* results.
* <p>
* Both sides of the cache are cleared.
*
* @param exc the exception for completing the requests
*/