source: trunk/abcl/src/org/armedbear/lisp/util/Finalizer.java

Last change on this file was 13251, checked in by ehuelsmann, 13 years ago

Set properties and correct attribution.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 6.2 KB
Line 
1/*
2 * Finalizer.java
3 *
4 * Copyright (C) 2011 Erik Huelsmann
5 * $Id: Finalizer.java 13251 2011-03-13 19:59:41Z ehuelsmann $
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
20 *
21 * As a special exception, the copyright holders of this library give you
22 * permission to link this library with independent modules to produce an
23 * executable, regardless of the license terms of these independent
24 * modules, and to copy and distribute the resulting executable under
25 * terms of your choice, provided that you also meet, for each linked
26 * independent module, the terms and conditions of the license of that
27 * module.  An independent module is a module which is not derived from
28 * or based on this library.  If you modify this library, you may extend
29 * this exception to your version of the library, but you are not
30 * obligated to do so.  If you do not wish to do so, delete this
31 * exception statement from your version.
32 */
33package org.armedbear.lisp.util;
34
35import java.lang.ref.ReferenceQueue;
36import java.util.Collections;
37import java.util.HashMap;
38import java.util.Iterator;
39import java.util.LinkedList;
40import java.util.Map;
41import java.util.WeakHashMap;
42
43/** Framework to monitor arbitrary objects to see if they have been
44 * garbage collected, running one or more runnables when they have.
45 */
46public class Finalizer {
47
48    /** Internal weak reference class which keeps a list of Runnables
49     * with finalizing actions to be executed.
50     */
51    private static class FinalizingWeakReference
52            extends java.lang.ref.WeakReference<Object> {
53
54        /** Queue of Runnables to be executed after the object is GC-ed. */
55        private LinkedList<Runnable> finalizers = new LinkedList<Runnable>();
56
57        FinalizingWeakReference(Object o, ReferenceQueue q, Runnable finalizer) {
58            super(o, q);
59            finalizers.add(finalizer);
60        }
61
62        /** Adds a finalizer.
63         *
64         * Finalizers will be run in reverse-registration order.
65         *
66         * @param finalizer The finalizer to be added.
67         */
68        void addFinalizer(Runnable finalizer) {
69            finalizers.add(finalizer);
70        }
71
72        /** Removes all registered finalizers. */
73        void cancelFinalizers() {
74            finalizers.clear();
75        }
76
77        /** Runs all finalizers registered. */
78        void run() {
79            Iterator<Runnable> iterator = finalizers.iterator();
80            while (iterator.hasNext()) {
81                iterator.next().run();
82            }
83        }
84    }
85
86    /** Queue for FinalizingWeakReference objects which need
87     * to have their references run because the associated
88     * object has been garbage collected
89     */
90    private static ReferenceQueue queue = null;
91
92    /** A map from objects to their associated FinalizingWeakReferences
93     * which is used by the routine which cancels finalization.
94     */
95    private static Map<Object, FinalizingWeakReference> references = null;
96
97    /** A map which maps the finalizing references onto themselves. This map
98     * makes sure that hard (as opposed to weak) references stay around to
99     * prevent garbage collection of the FinalizingWeakReferences before the
100     * referred objects are.
101     */
102    private static Map<FinalizingWeakReference, FinalizingWeakReference> anchor = null;
103
104    /** Checks that the internal administration variables and thread have been
105     * correctly set up.  This solution allows the GC monitoring thread to be
106     * started as late as its first use.
107     */
108    synchronized private static void checkQueue() {
109        if (queue == null) {
110            queue = new ReferenceQueue();
111            references = Collections.synchronizedMap(new WeakHashMap<Object, FinalizingWeakReference>());
112            anchor = Collections.synchronizedMap(new HashMap<FinalizingWeakReference, FinalizingWeakReference>());
113
114            Thread handler =
115                    new Thread(new Runnable() {
116
117                public void run() {
118                    while (true) {
119                        try {
120                            FinalizingWeakReference ref =
121                                    (FinalizingWeakReference) queue.remove();
122                            anchor.remove(ref);
123                            ref.run();
124                        } catch (InterruptedException i) {
125                        }
126                    }
127                }
128            }, "ABCL finalizer");
129
130            handler.setPriority(Thread.MAX_PRIORITY);
131            handler.setDaemon(true);
132            handler.start();
133        }
134    }
135
136    /** Schedules a Runnable to be run after garbage collection of the object.
137     *
138     * Note that the Runnable can't contain references to the object to be
139     * collected: it will disable garbage collection of the object.
140     *
141     * @param o The object to monitor for garbage collection
142     * @param r The routine to be executed after GC-ing the object
143     */
144    public static void addFinalizer(Object o, Runnable r) {
145        if (queue == null) {
146            checkQueue();
147        }
148
149        FinalizingWeakReference ref = references.get(o);
150        if (ref != null) {
151            ref.addFinalizer(r);
152        } else {
153            ref = new FinalizingWeakReference(o, queue, r);
154            references.put(o, ref);
155            anchor.put(ref, ref);
156        }
157    }
158
159    /** Cancels any references scheduled to be run after garbage
160     * collection of the argument 'o'.
161     *
162     * @param o Object to cancel references for
163     */
164    public static void clearFinalizers(Object o) {
165        FinalizingWeakReference ref = references.get(o);
166
167        if (ref != null) {
168            ref.cancelFinalizers();
169            anchor.remove(ref);
170        }
171    }
172}
Note: See TracBrowser for help on using the repository browser.