blob: 71b884804507a431092f24a1ffe619bfca37a9cc [file] [log] [blame]
/*
* 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 org.apache.sis.internal.system;
import org.apache.sis.util.Static;
import org.apache.sis.util.logging.Logging;
/**
* Utilities methods for threads. This class declares in a single place every {@link ThreadGroup} used in SIS.
* Their intent is to bring some order in debugger information, by grouping the threads created by SIS together
* under the same parent tree node.
*
* <h2>Note on dependencies</h2>
* This class shall not depend on {@link ReferenceQueueConsumer} or {@link DelayedExecutor},
* because initialization of those classes create new threads. However it is okay to have
* dependencies the other way around.
*
* @author Martin Desruisseaux (Geomatys)
* @version 0.7
* @since 0.3
* @module
*/
final class Threads extends Static {
/**
* The parent of every threads declared in this class. This parent will be declared as close
* as possible to the root of all thread groups (i.e. not as an application thread subgroup).
* The intent is to separate the library thread groups from the user application thread groups.
*/
static final ThreadGroup SIS;
static {
ThreadGroup parent = Thread.currentThread().getThreadGroup();
try {
ThreadGroup candidate;
while ((candidate = parent.getParent()) != null) {
parent = candidate;
}
} catch (SecurityException e) {
// If we are not allowed to get the parent, stop there.
// We went up in the tree as much as we were allowed to.
}
SIS = new ThreadGroup(parent, "Apache SIS");
}
/**
* The sub-group for daemon threads, usually for resources disposal.
*/
static final ThreadGroup DAEMONS = new ThreadGroup(SIS, "Daemons") {
@Override public void uncaughtException(final Thread thread, final Throwable exception) {
Logging.severeException(Logging.getLogger(Loggers.SYSTEM), thread.getClass(), "run", exception);
}
};
/* -------------------------------------------------------------------------------------
* Every non-final static variables below this point are initialized by other classes,
* like DaemonThread or Executors - this class will never initialize those variables by
* itself. All initialization shall be performed in a synchronized (Thread.class) block.
* ------------------------------------------------------------------------------------- */
/**
* The tail of a chain of {@code DaemonThread}s created by the {@code sis-utility} module.
* Other modules need to maintain their own chain, if any. See the {@link DaemonThread}
* javadoc for more information.
*/
static DaemonThread lastCreatedDaemon;
/**
* Do not allows instantiation of this class.
*/
private Threads() {
}
/**
* Sends a kill signal to all daemon threads created by the {@code sis-utility} module,
* and waits for the threads to die before to return.
*
* <p><strong>This method is for internal use by Apache SIS shutdown hooks only.</strong>
* Users should never invoke this method explicitly.</p>
*
* @param stopWaitingAt a {@link System#nanoTime()} value telling when to stop waiting.
* This is used for preventing shutdown process to block an indefinite amount of time.
* @throws InterruptedException if an other thread invoked {@link Thread#interrupt()} while
* we were waiting for the daemon threads to die.
*/
static synchronized void shutdown(final long stopWaitingAt) throws InterruptedException {
DaemonThread.killAll(lastCreatedDaemon, stopWaitingAt);
}
}