43 *
44 * <p> A cleaner tracks a referent object and encapsulates a thunk of arbitrary
45 * cleanup code. Some time after the GC detects that a cleaner's referent has
46 * become phantom-reachable, the reference-handler thread will run the cleaner.
47 * Cleaners may also be invoked directly; they are thread safe and ensure that
48 * they run their thunks at most once.
49 *
50 * <p> Cleaners are not a replacement for finalization. They should be used
51 * only when the cleanup code is extremely simple and straightforward.
52 * Nontrivial cleaners are inadvisable since they risk blocking the
53 * reference-handler thread and delaying further cleanup and finalization.
54 *
55 *
56 * @author Mark Reinhold
57 */
58
59 public class Cleaner
60 extends PhantomReference<Object>
61 {
62
63 // Dummy reference queue, needed because the PhantomReference constructor
64 // insists that we pass a queue. Nothing will ever be placed on this queue
65 // since the reference handler invokes cleaners explicitly.
66 //
67 private static final ReferenceQueue<Object> dummyQueue = new ReferenceQueue<>();
68
69 // Doubly-linked list of live cleaners, which prevents the cleaners
70 // themselves from being GC'd before their referents
71 //
72 static private Cleaner first = null;
73
74 private Cleaner
75 next = null,
76 prev = null;
77
78 private static synchronized Cleaner add(Cleaner cl) {
79 if (first != null) {
80 cl.next = first;
81 first.prev = cl;
82 }
83 first = cl;
84 return cl;
85 }
86
87 private static synchronized boolean remove(Cleaner cl) {
88
95 if (cl.next != null)
96 first = cl.next;
97 else
98 first = cl.prev;
99 }
100 if (cl.next != null)
101 cl.next.prev = cl.prev;
102 if (cl.prev != null)
103 cl.prev.next = cl.next;
104
105 // Indicate removal by pointing the cleaner to itself
106 cl.next = cl;
107 cl.prev = cl;
108 return true;
109
110 }
111
112 private final Runnable thunk;
113
114 private Cleaner(Object referent, Runnable thunk) {
115 super(referent, dummyQueue);
116 this.thunk = thunk;
117 }
118
119 /**
120 * Creates a new cleaner.
121 *
122 * @param ob the referent object to be cleaned
123 * @param thunk
124 * The cleanup code to be run when the cleaner is invoked. The
125 * cleanup code is run directly from the reference-handler thread,
126 * so it should be as simple and straightforward as possible.
127 *
128 * @return The new cleaner
129 */
130 public static Cleaner create(Object ob, Runnable thunk) {
131 if (thunk == null)
132 return null;
133 return add(new Cleaner(ob, thunk));
134 }
135
|
43 *
44 * <p> A cleaner tracks a referent object and encapsulates a thunk of arbitrary
45 * cleanup code. Some time after the GC detects that a cleaner's referent has
46 * become phantom-reachable, the reference-handler thread will run the cleaner.
47 * Cleaners may also be invoked directly; they are thread safe and ensure that
48 * they run their thunks at most once.
49 *
50 * <p> Cleaners are not a replacement for finalization. They should be used
51 * only when the cleanup code is extremely simple and straightforward.
52 * Nontrivial cleaners are inadvisable since they risk blocking the
53 * reference-handler thread and delaying further cleanup and finalization.
54 *
55 *
56 * @author Mark Reinhold
57 */
58
59 public class Cleaner
60 extends PhantomReference<Object>
61 {
62
63 // Doubly-linked list of live cleaners, which prevents the cleaners
64 // themselves from being GC'd before their referents
65 //
66 static private Cleaner first = null;
67
68 private Cleaner
69 next = null,
70 prev = null;
71
72 private static synchronized Cleaner add(Cleaner cl) {
73 if (first != null) {
74 cl.next = first;
75 first.prev = cl;
76 }
77 first = cl;
78 return cl;
79 }
80
81 private static synchronized boolean remove(Cleaner cl) {
82
89 if (cl.next != null)
90 first = cl.next;
91 else
92 first = cl.prev;
93 }
94 if (cl.next != null)
95 cl.next.prev = cl.prev;
96 if (cl.prev != null)
97 cl.prev.next = cl.next;
98
99 // Indicate removal by pointing the cleaner to itself
100 cl.next = cl;
101 cl.prev = cl;
102 return true;
103
104 }
105
106 private final Runnable thunk;
107
108 private Cleaner(Object referent, Runnable thunk) {
109 super(referent, null);
110 this.thunk = thunk;
111 }
112
113 /**
114 * Creates a new cleaner.
115 *
116 * @param ob the referent object to be cleaned
117 * @param thunk
118 * The cleanup code to be run when the cleaner is invoked. The
119 * cleanup code is run directly from the reference-handler thread,
120 * so it should be as simple and straightforward as possible.
121 *
122 * @return The new cleaner
123 */
124 public static Cleaner create(Object ob, Runnable thunk) {
125 if (thunk == null)
126 return null;
127 return add(new Cleaner(ob, thunk));
128 }
129
|