David Holmes wrote:
> Sun "fixed" this in Java 5.0. However, while the obvious fix
> is to clarify what "active" thread means for ThreadGroup, they
> didn't update the spec but simply decided they could interpret
> it how they wanted. So I can't tell you exactly what they did
> because it is implementation detail.
Running:
Thread t = new Thread("MyThread");
System.out.println(t.getThreadGroup());
Thread.currentThread().getThreadGroup().list();
on JDK 1.5 shows that the unstarted Thread considers itself to be part
of the ThreadGroup but not vice versa.
So it appears they went for the "obvious" solution of only adding the
Thread to the ThreadGroup when it is started.
> I will note that you also have to consider what it means for
> a ThreadGroup to be "empty" for daemon-ness and destroy purposes.
Thanks for the hint :-) So this means that we'll need a count in
ThreadGroup of unstarted threads.
I've attached my first stab at implementing this.
Regards,
Jeroen
Index: java/lang/ThreadGroup.java
===================================================================
RCS file: /cvsroot/classpath/classpath/java/lang/ThreadGroup.java,v
retrieving revision 1.17
diff -u -r1.17 ThreadGroup.java
--- java/lang/ThreadGroup.java 6 Dec 2004 20:43:13 -0000 1.17
+++ java/lang/ThreadGroup.java 10 Dec 2004 08:47:52 -0000
@@ -70,9 +70,12 @@
/** The group name, non-null. */
final String name;
- /** The threads in the group. */
+ /** The active threads in the group. */
private final Vector threads = new Vector();
+ /** The number of inactive threads in the group */
+ private int inactiveThreads;
+
/** Child thread groups, or null when this group is destroyed. */
private Vector groups = new Vector();
@@ -695,7 +698,8 @@
}
/**
- * Add a thread to the group. Called by Thread constructors.
+ * Add a thread to the group. Called by the VM for Threads
+ * started in native code, or by Thread.start() for Java threads.
*
* @param t the thread to add, non-null
* @throws IllegalThreadStateException if the group is destroyed
@@ -708,6 +712,24 @@
}
/**
+ * Increment the count of inactive threads. Whenever a Thread
+ * object is created this count should be incremented so that
+ * we know that the group isn't empty.
+ */
+ final synchronized void addInactiveThread()
+ {
+ inactiveThreads++;
+ }
+
+ /**
+ * Decrement the count inactive threads.
+ */
+ final synchronized void removeInactiveThread()
+ {
+ inactiveThreads--;
+ }
+
+ /**
* Called by the VM to remove a thread that has died.
*
* @param t the thread to remove, non-null
@@ -720,7 +742,8 @@
threads.remove(t);
t.group = null;
// Daemon groups are automatically destroyed when all their threads die.
- if (daemon_flag && groups.size() == 0 && threads.size() == 0)
+ if (daemon_flag && groups.size() == 0
+ && threads.size() == 0 && inactiveThreads == 0)
{
// We inline destroy to avoid the access check.
groups = null;
@@ -738,7 +761,8 @@
{
groups.remove(g);
// Daemon groups are automatically destroyed when all their threads die.
- if (daemon_flag && groups.size() == 0 && threads.size() == 0)
+ if (daemon_flag && groups.size() == 0
+ && threads.size() == 0 && inactiveThreads == 0)
{
// We inline destroy to avoid the access check.
groups = null;
Index: java/lang/Thread.java
===================================================================
RCS file: /cvsroot/classpath/classpath/java/lang/Thread.java,v
retrieving revision 1.10
diff -u -r1.10 Thread.java
--- java/lang/Thread.java 6 Dec 2004 20:43:13 -0000 1.10
+++ java/lang/Thread.java 10 Dec 2004 08:47:52 -0000
@@ -339,7 +339,7 @@
daemon = current.daemon;
contextClassLoader = current.contextClassLoader;
- group.addThread(this);
+ group.addInactiveThread();
InheritableThreadLocal.newChildThread(this);
}
@@ -824,6 +824,9 @@
throw new IllegalThreadStateException();
VMThread.create(this, stacksize);
+
+ group.addThread(this);
+ group.removeInactiveThread();
}
/**
@@ -970,4 +973,14 @@
group.removeThread(this);
vmThread = null;
}
+
+ /**
+ * If we die before ever having been actived, we need to remove
+ * ourself from the ThreadGroup inactive count.
+ */
+ protected void finalize() throws Throwable
+ {
+ if (group != null)
+ group.removeInactiveThread();
+ }
}
_______________________________________________
Classpath mailing list
[EMAIL PROTECTED]
http://lists.gnu.org/mailman/listinfo/classpath