Package com.sun.jini.jeri.internal.runtime

Source Code of com.sun.jini.jeri.internal.runtime.JvmLifeSupport

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 com.sun.jini.jeri.internal.runtime;

import com.sun.jini.thread.NewThreadAction;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

/**
* This class maintains a thread if necessary, in the wait state, to prevent
* the jvm shutting down while remote objects hold strong references in the
* DGC.
*
* This implementation is more about scalability than performance, when a jvm
* only has a small number of remote objects exported, blocking is not likely
* to cause a performance problem, access to keepAliveCount blocked.
*
* However with very large numbers of remote objects exported, in a dynamic
* environment, blocking is unlikely to be an issue, in this case the read locks
* will remain uncontended as the blocking write lock is only required as
* the number of exported object approach zero.
*
* If the thread is interrupted, it will pass away, regardless of the number of
* objects exported.
*
* @since 2.2.0
* @author Peter Firmstone
*/
public class JvmLifeSupport {
    /** lock guarding keepAliveCount and keeper */
    private final ReadWriteLock rwl;
    private final Lock rl;
    private final Lock wl;

    /** number of objects exported with keepAlive == true */
    private final AtomicInteger keepAliveCount;

    /** thread to keep VM alive while keepAliveCount > 0 */
    private volatile Thread keeper;
   
    JvmLifeSupport(){
        rwl = new ReentrantReadWriteLock();
        rl = rwl.readLock();
        wl = rwl.writeLock();
        keepAliveCount = new AtomicInteger();
        keeper = null;
    }
   
    /**
     * Increments the count of objects exported with keepAlive true,
     * starting a non-daemon thread if necessary.
     *
     * The old implementation contained in ObjectTable, used synchronization
     * on a single lock for incrementing and decrementing to judge when an
     * idle thread should be created or interrupted.
     *
     **/
    void incrementKeepAliveCount() {
        int value;
        rl.lock();
        try {
            value = keepAliveCount.getAndIncrement();
        } finally {
            rl.unlock();
        }
        if (value < 3){
            check();
        }    
    }

    /**
     * Decrements the count of objects exported with keepAlive true,
     * stopping the non-daemon thread if decremented to zero.
     **/
    void decrementKeepAliveCount() {
        int value;
        rl.lock();
        try {
            value = keepAliveCount.decrementAndGet();
        } finally {
            rl.unlock();
        }
        if (value < 3){
            check();
        }     
    }
   
    private void check(){
        wl.lock();
        try {
            int count = keepAliveCount.get();
            if (count == 0){
                assert keeper != null;
                AccessController.doPrivileged(new PrivilegedAction() {
                    public Object run() {
                        keeper.interrupt();
                        return null;
                    }
                });
                keeper = null;
            } else if ( count > 0){
                if (keeper == null) {
                    // This thread keeps the jvm alive, while remote objects
                    // exist and all local processes have completed.
                    keeper = (Thread) AccessController.doPrivileged(
                    new NewThreadAction(new Runnable() {
                        public void run() {
                            try {
                                while (!Thread.currentThread().isInterrupted()) {
                                    Thread.sleep(Long.MAX_VALUE);
                                }
                            } catch (InterruptedException e) {
                                // pass away if interrupted
                            }
                        }
                    }, "KeepAlive", false));
                    keeper.start();
                }
            }
        } finally {
            wl.unlock();
        }
    }
}
TOP

Related Classes of com.sun.jini.jeri.internal.runtime.JvmLifeSupport

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.