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

it.tidalwave.netbeans.modules.openide.util.ActiveQueue Maven / Gradle / Ivy

The newest version!
/***********************************************************************************************************************
 *
 * blueBill Mobile - Android - open source birding
 * Copyright (C) 2009-2011 by Tidalwave s.a.s. (http://www.tidalwave.it)
 *
 ***********************************************************************************************************************
 *
 * 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.
 *
 ***********************************************************************************************************************
 *
 * WWW: http://bluebill.tidalwave.it/mobile
 * SCM: https://java.net/hg/bluebill-mobile~android-src
 *
 **********************************************************************************************************************/
/***********************************************************************************************************************
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 **********************************************************************************************************************/
package it.tidalwave.netbeans.modules.openide.util;

import java.lang.ref.Reference;
import java.lang.ref.ReferenceQueue;
import java.util.logging.Level;
import java.util.logging.Logger;

/***********************************************************************************************************************
 *
 * @author  Fabrizio Giudici
 * @version $Id: $
 *
 **********************************************************************************************************************/
public final class ActiveQueue extends ReferenceQueue implements Runnable {

    private static final Logger LOGGER = Logger.getLogger(ActiveQueue.class.getName().replace('$', '.'));
    private static ActiveQueue activeReferenceQueue;
    /** number of known outstanding references */
    private int count;
    private boolean deprecated;

    ActiveQueue(boolean deprecated) {
        super();
        this.deprecated = deprecated;
    }

    public static synchronized ReferenceQueue queue() {
        if (activeReferenceQueue == null) {
            activeReferenceQueue = new ActiveQueue(false);
        }

        activeReferenceQueue.ping();

        return activeReferenceQueue;
    }

//    @Override
//    public Reference poll() {
//        throw new UnsupportedOperationException();
//    }

    @Override
    public Reference remove(long timeout) throws IllegalArgumentException, InterruptedException {
        throw new InterruptedException();
    }

    @Override
    public Reference remove() throws InterruptedException {
        throw new InterruptedException();
    }

    public void run() {
        while (true) {
            try {
                Reference ref = super.remove(0);
                LOGGER.finer("dequeued reference");
                if (!(ref instanceof Runnable)) {
                    LOGGER.warning("A reference not implementing runnable has been added to the Utilities.activeReferenceQueue(): " + ref.getClass());
                    continue;
                }
                if (deprecated) {
                    LOGGER.warning("Utilities.ACTIVE_REFERENCE_QUEUE has been deprecated for " + ref.getClass() + " use Utilities.activeReferenceQueue");
                }
                // do the cleanup
                try {
                    ((Runnable) ref).run();
                } catch (ThreadDeath td) {
                    throw td;
                } catch (Throwable t) {
                    // Should not happen.
                    // If it happens, it is a bug in client code, notify!
                    LOGGER.log(Level.WARNING, null, t);
                } finally {
                    // to allow GC
                    ref = null;
                }
            } catch (InterruptedException ex) {
                // Can happen during VM shutdown, it seems. Ignore.
                continue;
            }
            synchronized (this) {
                assert count > 0;
                count--;
                if (count == 0) {
                    // We have processed all we have to process (for now at least).
                    // Could be restarted later if ping() called again.
                    // This could also happen in case someone called queue() once and tried
                    // to use it for several references; in that case run() might never be called on
                    // the later ones to be collected. Can't really protect against that situation.
                    // See issue #86625 for details.
                    LOGGER.fine("stopping thread");
                    break;
                }
            }
        }
    }

    synchronized void ping() {
        if (count == 0) {
            Thread t = new Thread(this, "Active Reference Queue Daemon");
            t.setPriority(Thread.MIN_PRIORITY);
            t.setDaemon(true);
            t.start();
            LOGGER.fine("starting thread");
        } else {
            LOGGER.finer("enqueuing reference");
        }
        count++;
    }
}