source: josm/trunk/src/org/openstreetmap/josm/tools/ListenableWeakReference.java@ 13502

Last change on this file since 13502 was 12798, checked in by Don-vip, 7 years ago

see #14794 - checkstyle

File size: 2.2 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.tools;
3
4import java.lang.ref.Reference;
5import java.lang.ref.ReferenceQueue;
6import java.lang.ref.WeakReference;
7
8import org.openstreetmap.josm.tools.bugreport.BugReport;
9
10/**
11 * This is a special weak reference that notifies a listener when it is no longer available.
12 *
13 * A special dereferenced-thread is used for this, so make sure your code is thread-safe.
14 * @author Michael Zangl
15 * @param <T> The weak reference
16 * @since 12181
17 */
18public class ListenableWeakReference<T> extends WeakReference<T> {
19 private static final ReferenceQueue<Object> GLOBAL_QUEUE = new ReferenceQueue<>();
20 private static Thread thread;
21 private Runnable runOnDereference;
22
23 /**
24 * Create a new {@link ListenableWeakReference}
25 * @param referent The object that is referenced
26 */
27 public ListenableWeakReference(T referent) {
28 this(referent, () -> { });
29 }
30
31 /**
32 * Create a new {@link ListenableWeakReference}
33 * @param referent The object that is referenced
34 * @param runOnDereference The runnable to run when the object is no longer referenced.
35 */
36 public ListenableWeakReference(T referent, Runnable runOnDereference) {
37 super(referent, GLOBAL_QUEUE);
38 this.runOnDereference = runOnDereference;
39 ensureQueueStarted();
40 }
41
42 /**
43 * This method is called after the object is dereferenced.
44 */
45 protected void onDereference() {
46 this.runOnDereference.run();
47 }
48
49 private static synchronized void ensureQueueStarted() {
50 if (thread == null) {
51 thread = new Thread(ListenableWeakReference::clean, "Weak reference cleaner");
52 thread.start();
53 }
54 }
55
56 private static void clean() {
57 boolean running = true;
58 try {
59 while (running) {
60 Reference<? extends Object> ref = GLOBAL_QUEUE.remove();
61 if (ref instanceof ListenableWeakReference) {
62 ((ListenableWeakReference<?>) ref).onDereference();
63 }
64 }
65 } catch (InterruptedException e) {
66 running = false;
67 BugReport.intercept(e).warn();
68 Thread.currentThread().interrupt();
69 }
70 }
71}
Note: See TracBrowser for help on using the repository browser.