blob: e6bc9db9200522c2dc307e94efba783a97b74ba1 [file] [log] [blame]
/**********************************************************************
* This file is part of "Object Teams Dynamic Runtime Environment"
*
* Copyright 2006-2010 Berlin Institute of Technology, Germany, and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Please visit http://www.eclipse.org/objectteams for updates and contact.
*
* Contributors:
* Berlin Institute of Technology - Initial API and implementation
**********************************************************************/
package org.objectteams;
import java.util.HashSet;
import java.util.WeakHashMap;
/**
* This class is for internal use, only.
*
* Maintain information about existing threads as to manage
* team activation per thread vs. globally.
*
* @author Chistine Hundt
* @author Stephan Herrmann
*/
public class TeamThreadManager {
private static Object token = new Object();
private static HashSet<ITeam> globalActiveTeams = new HashSet<ITeam>();
private static WeakHashMap<ITeam,Object> teamsWithActivationInheritance = new WeakHashMap<ITeam,Object>();
private static HashSet<Thread> existingThreads = new HashSet<Thread>();
public static boolean newThreadStarted(boolean isMain, Thread parent) {
Thread currentThread = Thread.currentThread();
// already registered?
if (existingThreads.contains(currentThread))
return false;
// workaround for application hang on Mac OS with Apple JVM:
if (System.getProperty("os.name").startsWith("Mac"))
if (currentThread.getName().equals("AWT-Shutdown"))
return false;
ITeam[] globalTeams;
ITeam[] inheritableTeams;
synchronized (TeamThreadManager.class) {
boolean isFirst = existingThreads.isEmpty();
existingThreads.add(currentThread);
if (isMain || isFirst) {
for (Thread thread : fetchSystemThreads(currentThread))
if (thread != null)
existingThreads.add(thread);
}
globalTeams = globalActiveTeams.toArray(new ITeam[globalActiveTeams.size()]);
inheritableTeams = teamsWithActivationInheritance.keySet().toArray(new ITeam[teamsWithActivationInheritance.size()]);
}
// activate teams outside synchronized block:
for (ITeam t : globalTeams)
t.activate(currentThread); // small version? global -> already registered...!
if (parent != null)
for (ITeam t : inheritableTeams)
if (t.internalIsActiveSpecificallyFor(parent))
t.activate(currentThread); // pass activation from parent to child thread
return true;
}
/* Fetch all existing threads existing at this point in time. Result array is padded with nulls. */
private static Thread[] fetchSystemThreads(Thread currentThread) {
ThreadGroup group = currentThread.getThreadGroup();
{
ThreadGroup parentGroup;
while ((parentGroup= group.getParent()) != null)
group = parentGroup;
}
int size = group.activeCount();
Thread[] allThreads;
do {
size += 2;
allThreads = new Thread[size];
} while (group.enumerate(allThreads) == size);
return allThreads;
}
public static void threadEnded() {
ITeam[] teamsToDeactivate = internalThreadEnded();
// + remove per thread activation:
for (ITeam t : teamsToDeactivate)
//t.deactivate(Thread.currentThread()); // small version?
t.deactivateForEndedThread(Thread.currentThread());
}
private synchronized static ITeam[] internalThreadEnded() {
existingThreads.remove(Thread.currentThread());
// fetch all global active teams for deactivation:
return globalActiveTeams.toArray(new ITeam[globalActiveTeams.size()]);
}
public synchronized static void addGlobalActiveTeam(ITeam t) {
globalActiveTeams.add(t);
}
public synchronized static void removeGlobalActiveTeam(ITeam t) {
globalActiveTeams.remove(t);
}
public static HashSet<Thread> getExistingThreads() {
return existingThreads;
}
public static void registerTeamForActivationInheritance(ITeam aTeam) {
teamsWithActivationInheritance.put(aTeam,token);
}
public static void unRegisterTeamForActivationInheritance(ITeam aTeam) {
teamsWithActivationInheritance.remove(aTeam);
}
}