1*b1cdbd2cSJim Jagielski /**************************************************************
2*b1cdbd2cSJim Jagielski  *
3*b1cdbd2cSJim Jagielski  * Licensed to the Apache Software Foundation (ASF) under one
4*b1cdbd2cSJim Jagielski  * or more contributor license agreements.  See the NOTICE file
5*b1cdbd2cSJim Jagielski  * distributed with this work for additional information
6*b1cdbd2cSJim Jagielski  * regarding copyright ownership.  The ASF licenses this file
7*b1cdbd2cSJim Jagielski  * to you under the Apache License, Version 2.0 (the
8*b1cdbd2cSJim Jagielski  * "License"); you may not use this file except in compliance
9*b1cdbd2cSJim Jagielski  * with the License.  You may obtain a copy of the License at
10*b1cdbd2cSJim Jagielski  *
11*b1cdbd2cSJim Jagielski  *   http://www.apache.org/licenses/LICENSE-2.0
12*b1cdbd2cSJim Jagielski  *
13*b1cdbd2cSJim Jagielski  * Unless required by applicable law or agreed to in writing,
14*b1cdbd2cSJim Jagielski  * software distributed under the License is distributed on an
15*b1cdbd2cSJim Jagielski  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*b1cdbd2cSJim Jagielski  * KIND, either express or implied.  See the License for the
17*b1cdbd2cSJim Jagielski  * specific language governing permissions and limitations
18*b1cdbd2cSJim Jagielski  * under the License.
19*b1cdbd2cSJim Jagielski  *
20*b1cdbd2cSJim Jagielski  *************************************************************/
21*b1cdbd2cSJim Jagielski 
22*b1cdbd2cSJim Jagielski 
23*b1cdbd2cSJim Jagielski 
24*b1cdbd2cSJim Jagielski package com.sun.star.lib.util;
25*b1cdbd2cSJim Jagielski 
26*b1cdbd2cSJim Jagielski import java.util.LinkedList;
27*b1cdbd2cSJim Jagielski 
28*b1cdbd2cSJim Jagielski /**
29*b1cdbd2cSJim Jagielski    Helper class to asynchronously execute finalize methods.
30*b1cdbd2cSJim Jagielski 
31*b1cdbd2cSJim Jagielski    Current JVMs seem not to be robust against long-running finalize methods, in
32*b1cdbd2cSJim Jagielski    that such long-running finalize methods may lead to OutOfMemoryErrors.  This
33*b1cdbd2cSJim Jagielski    class mitigates the problem by asynchronously shifting the bodies of
34*b1cdbd2cSJim Jagielski    potentially long-running finalize methods into an extra thread.  Classes that
35*b1cdbd2cSJim Jagielski    make use of this in their finalize methods are the proxies used in the
36*b1cdbd2cSJim Jagielski    intra-process JNI UNO bridge and the inter-process Java URP UNO bridge (where
37*b1cdbd2cSJim Jagielski    in both cases finalizers lead to synchronous UNO release calls).
38*b1cdbd2cSJim Jagielski 
39*b1cdbd2cSJim Jagielski    If JVMs are getting more mature and should no longer have problems with
40*b1cdbd2cSJim Jagielski    long-running finalize mehtods, this class could be removed again.
41*b1cdbd2cSJim Jagielski */
42*b1cdbd2cSJim Jagielski public final class AsynchronousFinalizer {
43*b1cdbd2cSJim Jagielski     /**
44*b1cdbd2cSJim Jagielski        Add a job to be executed asynchronously.
45*b1cdbd2cSJim Jagielski 
46*b1cdbd2cSJim Jagielski        The run method of the given job is called exactly once.  If it terminates
47*b1cdbd2cSJim Jagielski        abnormally by throwing any Throwable, that is ignored.
48*b1cdbd2cSJim Jagielski 
49*b1cdbd2cSJim Jagielski        @param job represents the body of some finalize method; must not be null.
50*b1cdbd2cSJim Jagielski     */
add(Job job)51*b1cdbd2cSJim Jagielski     public static void add(Job job) {
52*b1cdbd2cSJim Jagielski         synchronized (queue) {
53*b1cdbd2cSJim Jagielski             boolean first = queue.isEmpty();
54*b1cdbd2cSJim Jagielski             queue.add(job);
55*b1cdbd2cSJim Jagielski             if (first) {
56*b1cdbd2cSJim Jagielski                 queue.notify();
57*b1cdbd2cSJim Jagielski             }
58*b1cdbd2cSJim Jagielski         }
59*b1cdbd2cSJim Jagielski     }
60*b1cdbd2cSJim Jagielski 
61*b1cdbd2cSJim Jagielski     /**
62*b1cdbd2cSJim Jagielski        An interface to represent bodies of finalize methods.
63*b1cdbd2cSJim Jagielski 
64*b1cdbd2cSJim Jagielski        Similar to Runnable, except that the run method may throw any Throwable
65*b1cdbd2cSJim Jagielski        (which is effectively ignored by AsynchronousFinalizer.add, similar to
66*b1cdbd2cSJim Jagielski        any Throwables raised by finalize being ignored).
67*b1cdbd2cSJim Jagielski     */
68*b1cdbd2cSJim Jagielski     public interface Job {
run()69*b1cdbd2cSJim Jagielski         void run() throws Throwable;
70*b1cdbd2cSJim Jagielski     }
71*b1cdbd2cSJim Jagielski 
72*b1cdbd2cSJim Jagielski     private static final LinkedList queue = new LinkedList();
73*b1cdbd2cSJim Jagielski 
74*b1cdbd2cSJim Jagielski     static {
75*b1cdbd2cSJim Jagielski         Thread t = new Thread() {
76*b1cdbd2cSJim Jagielski                 public void run() {
77*b1cdbd2cSJim Jagielski                     for (;;) {
78*b1cdbd2cSJim Jagielski                         Job j;
79*b1cdbd2cSJim Jagielski                         synchronized (queue) {
80*b1cdbd2cSJim Jagielski                             while (queue.isEmpty()) {
81*b1cdbd2cSJim Jagielski                                 try {
82*b1cdbd2cSJim Jagielski                                     queue.wait();
83*b1cdbd2cSJim Jagielski                                 } catch (InterruptedException e) {}
84*b1cdbd2cSJim Jagielski                             }
85*b1cdbd2cSJim Jagielski                             j = (Job) queue.remove(0);
86*b1cdbd2cSJim Jagielski                         }
87*b1cdbd2cSJim Jagielski                         try {
88*b1cdbd2cSJim Jagielski                             j.run();
89*b1cdbd2cSJim Jagielski                         } catch (Throwable e) {}
90*b1cdbd2cSJim Jagielski                     }
91*b1cdbd2cSJim Jagielski                 }
92*b1cdbd2cSJim Jagielski             };
93*b1cdbd2cSJim Jagielski         t.setDaemon(true);
t.start()94*b1cdbd2cSJim Jagielski         t.start();
95*b1cdbd2cSJim Jagielski     }
96*b1cdbd2cSJim Jagielski 
AsynchronousFinalizer()97*b1cdbd2cSJim Jagielski     private AsynchronousFinalizer() {}
98*b1cdbd2cSJim Jagielski }
99