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

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

sonar - squid:S2189 - Loops should not be infinite

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 * @since 12181
16 *
17 * @param <T> The weak reference
18 */
19public class ListenableWeakReference<T> extends WeakReference<T> {
20 private static final ReferenceQueue<Object> GLOBAL_QUEUE = new ReferenceQueue<>();
21 private static Thread thread;
22 private Runnable runOnDereference;
23
24 /**
25 * Create a new {@link ListenableWeakReference}
26 * @param referent The object that is referenced
27 */
28 public ListenableWeakReference(T referent) {
29 this(referent, () -> { });
30 }
31
32 /**
33 * Create a new {@link ListenableWeakReference}
34 * @param referent The object that is referenced
35 * @param runOnDereference The runnable to run when the object is no longer referenced.
36 */
37 public ListenableWeakReference(T referent, Runnable runOnDereference) {
38 super(referent, GLOBAL_QUEUE);
39 this.runOnDereference = runOnDereference;
40 ensureQueueStarted();
41 }
42
43 /**
44 * This method is called after the object is dereferenced.
45 */
46 protected void onDereference() {
47 this.runOnDereference.run();
48 }
49
50 private static synchronized void ensureQueueStarted() {
51 if (thread == null) {
52 thread = new Thread(ListenableWeakReference::clean, "Weak reference cleaner");
53 thread.start();
54 }
55 }
56
57 private static void clean() {
58 boolean running = true;
59 try {
60 while (running) {
61 Reference<? extends Object> ref = GLOBAL_QUEUE.remove();
62 if (ref instanceof ListenableWeakReference) {
63 ((ListenableWeakReference<?>) ref).onDereference();
64 }
65 }
66 } catch (InterruptedException e) {
67 running = false;
68 BugReport.intercept(e).warn();
69 Thread.currentThread().interrupt();
70 }
71 }
72}
Note: See TracBrowser for help on using the repository browser.