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