comparison src/fschmidt/util/java/Memoizer.java @ 68:00520880ad02

add fschmidt source
author Franklin Schmidt <fschmidt@gmail.com>
date Sun, 05 Oct 2025 17:24:15 -0600
parents
children
comparison
equal deleted inserted replaced
67:9d0fefce6985 68:00520880ad02
1 package fschmidt.util.java;
2
3 import java.util.Collection;
4 import java.util.HashMap;
5 import java.util.Map;
6 import java.util.concurrent.Callable;
7 import java.util.concurrent.CancellationException;
8 import java.util.concurrent.ConcurrentHashMap;
9 import java.util.concurrent.ConcurrentMap;
10 import java.util.concurrent.ExecutionException;
11 import java.util.concurrent.Future;
12
13 // based on Memoizer from Java Concurrency in Practice
14
15 public final class Memoizer<A,V> implements Computable<A,V> {
16 private final ConcurrentMap<A, Future<V>> cache
17 = new ConcurrentHashMap<A, Future<V>>();
18 private final Computable<A,V> comp;
19
20 public Memoizer(Computable<A,V> comp) {
21 this.comp = comp;
22 }
23
24 public V get(final A arg) throws ComputationException {
25 while (true) {
26 Future<V> f = cache.get(arg);
27 if (f == null) {
28 Callable<V> eval = new Callable<V>() {
29 public V call() throws Exception {
30 return comp.get(arg);
31 }
32 };
33 FastFuture<V> ft = new FastFuture<V>(eval);
34 f = cache.putIfAbsent(arg, ft);
35 if (f == null) {
36 f = ft;
37 ft.run();
38 }
39 }
40 try {
41 return f.get();
42 } catch (InterruptedException e) {
43 throw new RuntimeException(e);
44 } catch (CancellationException e) {
45 cache.remove(arg, f);
46 } catch (ExecutionException e) {
47 throw ComputationException.newInstance(e);
48 }
49 }
50 }
51
52 public Map<A,V> get(final Collection<A> args) throws ComputationException {
53 outer:
54 while (true) {
55 Map<A,Future<V>> fmap = new HashMap<A,Future<V>>();
56 for( final A arg : args ) {
57 Future<V> f = cache.get(arg);
58 if (f == null) {
59 Callable<V> eval = new Callable<V>() {
60 public V call() throws Exception {
61 return comp.get(arg);
62 }
63 };
64 FastFuture<V> ft = new FastFuture<V>(eval);
65 f = cache.putIfAbsent(arg, ft);
66 if (f == null) {
67 f = ft;
68 ft.run();
69 }
70 }
71 fmap.put(arg,f);
72 }
73 Map<A,V> map = new HashMap<A,V>();
74 for( Map.Entry<A,Future<V>> entry : fmap.entrySet() ) {
75 A arg = entry.getKey();
76 Future<V> f = entry.getValue();
77 try {
78 map.put( arg, f.get() );
79 } catch (InterruptedException e) {
80 throw new RuntimeException(e);
81 } catch (CancellationException e) {
82 cache.remove(arg, f);
83 continue outer;
84 } catch (ExecutionException e) {
85 throw ComputationException.newInstance(e);
86 }
87 }
88 return map;
89 }
90 }
91
92 public void remove(final A arg) {
93 cache.remove(arg);
94 }
95 /*
96 public void clear() {
97 cache.clear();
98 }
99 */
100 }