<commit_before>/*
 * #%L
 * mosaic-tools-threading
 * %%
 * Copyright (C) 2010 - 2012 Institute e-Austria Timisoara (Romania)
 * %%
 * 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.
 * #L%
 */

package eu.mosaic_cloud.tools.threading.implementations.basic;


import java.lang.Thread.UncaughtExceptionHandler;
import java.lang.ref.WeakReference;
import java.util.Iterator;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;

import eu.mosaic_cloud.tools.exceptions.core.ExceptionTracer;
import eu.mosaic_cloud.tools.exceptions.core.FallbackExceptionTracer;
import eu.mosaic_cloud.tools.threading.core.ThreadConfiguration;
import eu.mosaic_cloud.tools.threading.core.ThreadController;
import eu.mosaic_cloud.tools.threading.core.ThreadingContext;
import eu.mosaic_cloud.tools.threading.tools.ThreadBundle;
import eu.mosaic_cloud.tools.threading.tools.Threading;

import com.google.common.base.Preconditions;


public final class BasicThreadingContext
		implements
			ThreadingContext,
			ThreadController,
			Iterable<Thread>
{
	private BasicThreadingContext (final ThreadGroup group, final ThreadConfiguration configuration)
	{
		super ();
		Preconditions.checkNotNull (group);
		Preconditions.checkNotNull (configuration);
		Preconditions.checkNotNull (configuration.owner);
		Preconditions.checkNotNull (configuration.exceptions);
		Preconditions.checkNotNull (configuration.catcher);
		Preconditions.checkState (System.getSecurityManager () instanceof BasicThreadingSecurityManager);
		this.owner = BasicThreadingContext.buildOwner (configuration);
		this.configuration = configuration;
		this.group = new BasicThreadGroup (group, this.configuration);
		this.defaultGroup = new BasicThreadGroup (this.group, configuration.setName ("default"));
		this.threads = ThreadBundle.create ();
		this.initialized = new AtomicBoolean (false);
		this.sealed = new AtomicBoolean (false);
	}
	
	// FIXME: This method is currently "half" implemented as it doesn't wait for threads not derived from `BasicThread`.
	@Override
	public final boolean await ()
	{
		return (this.threads.await ());
	}
	
	@Override
	public final boolean await (final long timeout)
	{
		return (this.threads.await (timeout));
	}
	
	// FIXME: Returned executors should extend `ThreadPoolExecutor` (or the like) and override certain methods for logging and error handling.
	@Override
	public final ExecutorService createCachedThreadPool (final ThreadConfiguration configuration)
	{
		return (Executors.unconfigurableExecutorService (Executors.newCachedThreadPool (this.createThreadFactory (configuration, true))));
	}
	
	@Override
	public final ExecutorService createFixedThreadPool (final ThreadConfiguration configuration, final int threads)
	{
		return (Executors.unconfigurableExecutorService (Executors.newFixedThreadPool (threads, this.createThreadFactory (configuration, true))));
	}
	
	@Override
	public final ScheduledExecutorService createScheduledThreadPool (final ThreadConfiguration configuration, final int coreThreads)
	{
		return (Executors.unconfigurableScheduledExecutorService (Executors.newScheduledThreadPool (coreThreads, this.createThreadFactory (configuration, true))));
	}
	
	@Override
	public final ExecutorService createSingleThreadExecutor (final ThreadConfiguration configuration)
	{
		return (Executors.unconfigurableExecutorService (Executors.newSingleThreadExecutor (this.createThreadFactory (configuration, false))));
	}
	
	@Override
	public final ScheduledExecutorService createSingleThreadScheduledExecutor (final ThreadConfiguration configuration)
	{
		return (Executors.unconfigurableScheduledExecutorService (Executors.newSingleThreadScheduledExecutor (this.createThreadFactory (configuration, false))));
	}
	
	@Override
	public final Thread createThread (final ThreadConfiguration configuration, final Runnable runnable)
	{
		Preconditions.checkState (this.isActive ());
		Preconditions.checkState (!this.isSealed ());
		return (new BasicThread (this.group, configuration, runnable, -1));
	}
	
	@Override
	public final ThreadFactory createThreadFactory (final ThreadConfiguration configuration)
	{
		return (this.createThreadFactory (configuration, true));
	}
	
	public final ThreadFactory createThreadFactory (final ThreadConfiguration configuration, final boolean index)
	{
		Preconditions.checkState (this.isActive ());
		Preconditions.checkState (!this.isSealed ());
		return (new BasicThreadFactory (new BasicThreadGroup (this.group, configuration), configuration, index));
	}
	
	public final void destroy ()
	{
		Preconditions.checkState (this.destroy (-1));
	}
	
	public final boolean destroy (final long timeout)
	{
		this.interrupt ();
		return (this.await (timeout));
	}
	
	@Override
	public final ThreadGroup getDefaultThreadGroup ()
	{
		return (this.defaultGroup);
	}
	
	public final void initialize ()
	{
		Preconditions.checkState (this.initialize (-1));
	}
	
	public final boolean initialize (final long timeout)
	{
		Preconditions.checkArgument (timeout >= -1);
		Preconditions.checkState (this.initialized.compareAndSet (false, true));
		return (true);
	}
	
	@Override
	public final void interrupt ()
	{
		this.threads.interrupt ();
	}
	
	@Override
	public final boolean isActive ()
	{
		if (!this.initialized.get ())
			return (false);
		final Object owner = this.configuration.owner.get ();
		if (owner == null)
			return (false);
		return (true);
	}
	
	@Override
	public final boolean isManaged (final Thread thread)
	{
		Preconditions.checkNotNull (thread);
		return (this.isManaged (thread.getThreadGroup ()));
	}
	
	@Override
	public final boolean isManaged (final ThreadGroup group)
	{
		Preconditions.checkNotNull (group);
		for (ThreadGroup parent = group; true; parent = parent.getParent ()) {
			if (parent == this.group)
				return (true);
			if (parent == null)
				return (false);
		}
	}
	
	@Override
	public final boolean isSealed ()
	{
		return (this.sealed.get ());
	}
	
	@Override
	public final Iterator<Thread> iterator ()
	{
		return (this.threads.iterator ());
	}
	<commit_msg>Hack threading context to say `unhandled` to terminated threads (which have no group)<commit_after>/*
 * #%L
 * mosaic-tools-threading
 * %%
 * Copyright (C) 2010 - 2012 Institute e-Austria Timisoara (Romania)
 * %%
 * 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.
 * #L%
 */

package eu.mosaic_cloud.tools.threading.implementations.basic;


import java.lang.Thread.UncaughtExceptionHandler;
import java.lang.ref.WeakReference;
import java.util.Iterator;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;

import eu.mosaic_cloud.tools.exceptions.core.ExceptionTracer;
import eu.mosaic_cloud.tools.exceptions.core.FallbackExceptionTracer;
import eu.mosaic_cloud.tools.threading.core.ThreadConfiguration;
import eu.mosaic_cloud.tools.threading.core.ThreadController;
import eu.mosaic_cloud.tools.threading.core.ThreadingContext;
import eu.mosaic_cloud.tools.threading.tools.ThreadBundle;
import eu.mosaic_cloud.tools.threading.tools.Threading;

import com.google.common.base.Preconditions;


public final class BasicThreadingContext
		implements
			ThreadingContext,
			ThreadController,
			Iterable<Thread>
{
	private BasicThreadingContext (final ThreadGroup group, final ThreadConfiguration configuration)
	{
		super ();
		Preconditions.checkNotNull (group);
		Preconditions.checkNotNull (configuration);
		Preconditions.checkNotNull (configuration.owner);
		Preconditions.checkNotNull (configuration.exceptions);
		Preconditions.checkNotNull (configuration.catcher);
		Preconditions.checkState (System.getSecurityManager () instanceof BasicThreadingSecurityManager);
		this.owner = BasicThreadingContext.buildOwner (configuration);
		this.configuration = configuration;
		this.group = new BasicThreadGroup (group, this.configuration);
		this.defaultGroup = new BasicThreadGroup (this.group, configuration.setName ("default"));
		this.threads = ThreadBundle.create ();
		this.initialized = new AtomicBoolean (false);
		this.sealed = new AtomicBoolean (false);
	}
	
	// FIXME: This method is currently "half" implemented as it doesn't wait for threads not derived from `BasicThread`.
	@Override
	public final boolean await ()
	{
		return (this.threads.await ());
	}
	
	@Override
	public final boolean await (final long timeout)
	{
		return (this.threads.await (timeout));
	}
	
	// FIXME: Returned executors should extend `ThreadPoolExecutor` (or the like) and override certain methods for logging and error handling.
	@Override
	public final ExecutorService createCachedThreadPool (final ThreadConfiguration configuration)
	{
		return (Executors.unconfigurableExecutorService (Executors.newCachedThreadPool (this.createThreadFactory (configuration, true))));
	}
	
	@Override
	public final ExecutorService createFixedThreadPool (final ThreadConfiguration configuration, final int threads)
	{
		return (Executors.unconfigurableExecutorService (Executors.newFixedThreadPool (threads, this.createThreadFactory (configuration, true))));
	}
	
	@Override
	public final ScheduledExecutorService createScheduledThreadPool (final ThreadConfiguration configuration, final int coreThreads)
	{
		return (Executors.unconfigurableScheduledExecutorService (Executors.newScheduledThreadPool (coreThreads, this.createThreadFactory (configuration, true))));
	}
	
	@Override
	public final ExecutorService createSingleThreadExecutor (final ThreadConfiguration configuration)
	{
		return (Executors.unconfigurableExecutorService (Executors.newSingleThreadExecutor (this.createThreadFactory (configuration, false))));
	}
	
	@Override
	public final ScheduledExecutorService createSingleThreadScheduledExecutor (final ThreadConfiguration configuration)
	{
		return (Executors.unconfigurableScheduledExecutorService (Executors.newSingleThreadScheduledExecutor (this.createThreadFactory (configuration, false))));
	}
	
	@Override
	public final Thread createThread (final ThreadConfiguration configuration, final Runnable runnable)
	{
		Preconditions.checkState (this.isActive ());
		Preconditions.checkState (!this.isSealed ());
		return (new BasicThread (this.group, configuration, runnable, -1));
	}
	
	@Override
	public final ThreadFactory createThreadFactory (final ThreadConfiguration configuration)
	{
		return (this.createThreadFactory (configuration, true));
	}
	
	public final ThreadFactory createThreadFactory (final ThreadConfiguration configuration, final boolean index)
	{
		Preconditions.checkState (this.isActive ());
		Preconditions.checkState (!this.isSealed ());
		return (new BasicThreadFactory (new BasicThreadGroup (this.group, configuration), configuration, index));
	}
	
	public final void destroy ()
	{
		Preconditions.checkState (this.destroy (-1));
	}
	
	public final boolean destroy (final long timeout)
	{
		this.interrupt ();
		return (this.await (timeout));
	}
	
	@Override
	public final ThreadGroup getDefaultThreadGroup ()
	{
		return (this.defaultGroup);
	}
	
	public final void initialize ()
	{
		Preconditions.checkState (this.initialize (-1));
	}
	
	public final boolean initialize (final long timeout)
	{
		Preconditions.checkArgument (timeout >= -1);
		Preconditions.checkState (this.initialized.compareAndSet (false, true));
		return (true);
	}
	
	@Override
	public final void interrupt ()
	{
		this.threads.interrupt ();
	}
	
	@Override
	public final boolean isActive ()
	{
		if (!this.initialized.get ())
			return (false);
		final Object owner = this.configuration.owner.get ();
		if (owner == null)
			return (false);
		return (true);
	}
	
	@Override
	public final boolean isManaged (final Thread thread)
	{
		Preconditions.checkNotNull (thread);
		// FIXME: It seems that "terminated" threads have no thread group...
		final ThreadGroup group = thread.getThreadGroup ();
		if (group == null)
			return (false);
		return (this.isManaged (group));
	}
	
	@Override
	public final boolean isManaged (final ThreadGroup group)
	{
		Preconditions.checkNotNull (group);
		for (ThreadGroup parent = group; true; parent = parent.getParent ()) {
			if (parent == this.group)
				return (true);
			if (parent == null)
				return (false);
		}
	}
	
	@Override
	public final boolean isSealed ()
	{
		return (this.sealed.get ());
	}
	
	@Override
	public final Iterator<Thread> iterator ()
	{
		return (this.threads.iterator ());
	}
	
{'fraction_non_alphanumeric': 0.09492933119626985, 'fraction_numerical': 0.0023313419787265046, 'mean_word_length': 5.25375854214123, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 9, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4633319', 'n_tokens_mistral': 3965, 'n_tokens_neox': 3705, 'n_words': 1029}