All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.codehaus.groovy.util.ReferenceManager Maven / Gradle / Ivy

There is a newer version: 3.9
Show newest version
/*
 * Copyright 2003-2010 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.codehaus.groovy.util;

import java.lang.ref.ReferenceQueue;
import java.util.concurrent.atomic.AtomicInteger;

public class ReferenceManager {
    private static class ThreadedReferenceManager extends ReferenceManager {
        private final Thread thread;
        private volatile boolean shouldRun = true; 
        public ThreadedReferenceManager(ReferenceQueue queue) {
            super(queue);
            thread = new Thread() {
                public void run() {
                    ReferenceQueue queue = getReferenceQueue();
                    java.lang.ref.Reference r=null;
                    while (shouldRun) {
                        try {
                            r = queue.remove(1000);
                        }  catch (InterruptedException e) {
                            break;
                        }
                        if (r==null) continue;
                        
                        if (r instanceof Reference) {
                            Reference ref = (Reference) r;
                            Finalizable holder = ref.getHandler();
                            if (holder!=null) holder.finalizeReference();
                        }                  
                        r.clear();
                        r=null;
                    }
                }
            };
            thread.setContextClassLoader(null);
            thread.setDaemon(true);
            thread.setName(ThreadedReferenceManager.class.getName());
            thread.start();
        }
        @Override
        public void stopThread() {
            shouldRun = false;
            thread.interrupt();
        }        
        @Override
        public String toString() {
            return "ReferenceManager(threaded, thread="+thread+")";
        }
    }

    public static ReferenceManager createThreadedManager(ReferenceQueue queue) {
        return new ThreadedReferenceManager(queue);
    }
    public static ReferenceManager createIdlingManager(ReferenceQueue queue) {
        return new ReferenceManager(queue);
    }
    public static ReferenceManager createCallBackedManager(ReferenceQueue queue) {
        return new ReferenceManager(queue){
            @Override
            public void removeStallEntries() {
                ReferenceQueue queue = getReferenceQueue();
                for(;;) {
                    java.lang.ref.Reference r = queue.poll();
                    if (r==null) break;
                    
                    if (r instanceof Reference) {
                        Reference ref = (Reference) r;
                        Finalizable holder = ref.getHandler();
                        if (holder!=null) holder.finalizeReference();
                    }
                    r.clear();
                    r=null;
                }
            }
            @Override
            public void afterReferenceCreation(Reference r) {
                removeStallEntries();
            }
            @Override
            public String toString() {
                return "ReferenceManager(callback)";
            }
        };
    }
    public static ReferenceManager createThresholdedIdlingManager(final ReferenceQueue queue, final ReferenceManager callback, final int threshold) {
        if (threshold<0) throw new IllegalArgumentException("threshold must not be below 0.");
       
        return new ReferenceManager(queue){
            private AtomicInteger refCnt = new AtomicInteger();
            private volatile ReferenceManager manager = createIdlingManager(queue);
            @Override
            public void afterReferenceCreation(Reference r) {
                if (manager==callback) {
                    callback.afterReferenceCreation(r);
                    return;
                }
                // we use the idle manager, so let us use the reference counter
                // we change the manager once the threshold is reached. There is
                // a small chance that the value will go beyond Integer.MAX_VALUE
                // so we check for values below 0 too. If threshold is low, then
                // this is unlikely to happen. If threshold is high, then we 
                // have all negative values as fall back
                int count = refCnt.incrementAndGet();
                if (count>threshold || count<0) {
                    manager = callback;
                }
            }
            @Override
            public String toString() {
                return "ReferenceManager(thresholded, current manager="+manager+", threshold="+refCnt.get()+"/"+threshold+")";
            }
        };        
    }  
    
    private ReferenceQueue queue;
    
    public ReferenceManager(ReferenceQueue queue) {
        this.queue = queue;
    }
       
    protected ReferenceQueue getReferenceQueue() {
        return queue;
    }
    
    public void afterReferenceCreation(Reference r) {}
    public void removeStallEntries() {}
    public void stopThread() {}
    
    @Override
    public String toString() {
        return "ReferenceManager(idling)";
    }
    
    private static final ReferenceBundle SOFT_BUNDLE, WEAK_BUNDLE;
    static {
        ReferenceQueue queue = new ReferenceQueue();
        ReferenceManager callBack = ReferenceManager.createCallBackedManager(queue);
        ReferenceManager manager  = ReferenceManager.createThresholdedIdlingManager(queue, callBack, 500);
        SOFT_BUNDLE = new ReferenceBundle(manager, ReferenceType.SOFT);
        WEAK_BUNDLE = new ReferenceBundle(manager, ReferenceType.WEAK);
    }
    
    public static ReferenceBundle getDefaultSoftBundle() {
        return SOFT_BUNDLE;
    }
    
    public static ReferenceBundle getDefaultWeakBundle() {
        return WEAK_BUNDLE;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy