[jboss-cvs] JBossAS SVN: r91879 - in projects/jboss-threads/trunk/main: src/main/java/org/jboss/threads and 1 other directory.

jboss-cvs-commits at lists.jboss.org jboss-cvs-commits at lists.jboss.org
Fri Jul 31 11:14:54 EDT 2009


Author: david.lloyd at jboss.com
Date: 2009-07-31 11:14:53 -0400 (Fri, 31 Jul 2009)
New Revision: 91879

Added:
   projects/jboss-threads/trunk/main/src/main/java/org/jboss/threads/ContextClassLoaderExecutor.java
   projects/jboss-threads/trunk/main/src/main/java/org/jboss/threads/ExceptionLoggingExecutor.java
   projects/jboss-threads/trunk/main/src/main/java/org/jboss/threads/InitializingExecutor.java
   projects/jboss-threads/trunk/main/src/main/java/org/jboss/threads/NullRunnable.java
   projects/jboss-threads/trunk/main/src/main/java/org/jboss/threads/PrivilegedExecutor.java
   projects/jboss-threads/trunk/main/src/main/java/org/jboss/threads/ThreadFactoryExecutor.java
   projects/jboss-threads/trunk/main/src/main/java/org/jboss/threads/ThreadNameExecutor.java
   projects/jboss-threads/trunk/main/src/main/java/org/jboss/threads/ThreadNameNotatingExecutor.java
   projects/jboss-threads/trunk/main/src/main/java/org/jboss/threads/ThreadPool.java
   projects/jboss-threads/trunk/main/src/main/java/org/jboss/threads/WrappingExecutor.java
   projects/jboss-threads/trunk/main/src/main/java/org/jboss/threads/WrappingThreadFactory.java
Removed:
   projects/jboss-threads/trunk/main/src/main/java/org/jboss/threads/ConfigurableExecutor.java
   projects/jboss-threads/trunk/main/src/main/java/org/jboss/threads/QueuelessThreadPoolExecutor.java
   projects/jboss-threads/trunk/main/src/main/java/org/jboss/threads/ResettingDirectExecutor.java
Modified:
   projects/jboss-threads/trunk/main/pom.xml
   projects/jboss-threads/trunk/main/src/main/java/org/jboss/threads/JBossExecutors.java
   projects/jboss-threads/trunk/main/src/main/java/org/jboss/threads/JBossThread.java
   projects/jboss-threads/trunk/main/src/main/java/org/jboss/threads/ProtectedExecutorService.java
Log:
Begin 1.1 refactor; new queueless ThreadPool; many cleanups to the executor impls and new helper methods

Modified: projects/jboss-threads/trunk/main/pom.xml
===================================================================
--- projects/jboss-threads/trunk/main/pom.xml	2009-07-31 15:01:29 UTC (rev 91878)
+++ projects/jboss-threads/trunk/main/pom.xml	2009-07-31 15:14:53 UTC (rev 91879)
@@ -7,9 +7,14 @@
     <groupId>org.jboss.threads</groupId>
     <artifactId>jboss-threads</artifactId>
     <packaging>jar</packaging>
-    <version>1.0.0.GA</version>
+    <version>1.1.0.CR1-SNAPSHOT</version>
     <dependencies>
         <dependency>
+            <groupId>org.jboss.logging</groupId>
+            <artifactId>jboss-logging-spi</artifactId>
+            <version>2.2.0.CR1</version>
+        </dependency>
+        <dependency>
             <groupId>junit</groupId>
             <artifactId>junit</artifactId>
             <version>3.8.1</version>
@@ -46,7 +51,7 @@
         <repository>
             <id>repository.jboss.org</id>
             <name>JBoss Maven2 Repository</name>
-            <url>${repository.url}</url>
+            <url>http://repository.jboss.org/maven2</url>
         </repository>
     </distributionManagement>
 </project>

Deleted: projects/jboss-threads/trunk/main/src/main/java/org/jboss/threads/ConfigurableExecutor.java
===================================================================
--- projects/jboss-threads/trunk/main/src/main/java/org/jboss/threads/ConfigurableExecutor.java	2009-07-31 15:01:29 UTC (rev 91878)
+++ projects/jboss-threads/trunk/main/src/main/java/org/jboss/threads/ConfigurableExecutor.java	2009-07-31 15:14:53 UTC (rev 91879)
@@ -1,32 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors.
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-
-package org.jboss.threads;
-
-import java.util.concurrent.Executor;
-
-/**
- * An executor upon which tasks may be executed
- */
-public interface ConfigurableExecutor {
-    void execute(Runnable task, DirectExecutor taskExecutor, RejectionPolicy policy, Executor handoffExecutor);
-}

Added: projects/jboss-threads/trunk/main/src/main/java/org/jboss/threads/ContextClassLoaderExecutor.java
===================================================================
--- projects/jboss-threads/trunk/main/src/main/java/org/jboss/threads/ContextClassLoaderExecutor.java	                        (rev 0)
+++ projects/jboss-threads/trunk/main/src/main/java/org/jboss/threads/ContextClassLoaderExecutor.java	2009-07-31 15:14:53 UTC (rev 91879)
@@ -0,0 +1,49 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.threads;
+
+class ContextClassLoaderExecutor implements DirectExecutor {
+
+    private final ClassLoader taskClassLoader;
+    private final DirectExecutor delegate;
+
+    ContextClassLoaderExecutor(final ClassLoader taskClassLoader, final DirectExecutor delegate) {
+        this.taskClassLoader = taskClassLoader;
+        this.delegate = delegate;
+    }
+
+    public void execute(final Runnable command) {
+        final Thread thr = Thread.currentThread();
+        ClassLoader old = thr.getContextClassLoader();
+        thr.setContextClassLoader(taskClassLoader);
+        try {
+            delegate.execute(command);
+        } finally {
+            thr.setContextClassLoader(old);
+        }
+    }
+
+    public String toString() {
+        return String.format("%s (classloader %s) -> %s", super.toString(), taskClassLoader, delegate);
+    }
+}

Added: projects/jboss-threads/trunk/main/src/main/java/org/jboss/threads/ExceptionLoggingExecutor.java
===================================================================
--- projects/jboss-threads/trunk/main/src/main/java/org/jboss/threads/ExceptionLoggingExecutor.java	                        (rev 0)
+++ projects/jboss-threads/trunk/main/src/main/java/org/jboss/threads/ExceptionLoggingExecutor.java	2009-07-31 15:14:53 UTC (rev 91879)
@@ -0,0 +1,48 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.threads;
+
+import org.jboss.logging.Logger;
+
+class ExceptionLoggingExecutor implements DirectExecutor {
+
+    private final DirectExecutor delegate;
+    private final Logger log;
+
+    ExceptionLoggingExecutor(final DirectExecutor delegate, final Logger log) {
+        this.delegate = delegate;
+        this.log = log;
+    }
+
+    public void execute(final Runnable command) {
+        try {
+            delegate.execute(command);
+        } catch (Throwable t) {
+            log.error("Exception thrown from thread task", t);
+        }
+    }
+
+    public String toString() {
+        return String.format("%s to \"%s\" -> %s", super.toString(), log.getName(), delegate);
+    }
+}

Added: projects/jboss-threads/trunk/main/src/main/java/org/jboss/threads/InitializingExecutor.java
===================================================================
--- projects/jboss-threads/trunk/main/src/main/java/org/jboss/threads/InitializingExecutor.java	                        (rev 0)
+++ projects/jboss-threads/trunk/main/src/main/java/org/jboss/threads/InitializingExecutor.java	2009-07-31 15:14:53 UTC (rev 91879)
@@ -0,0 +1,43 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.threads;
+
+class InitializingExecutor implements DirectExecutor {
+
+    private final Runnable initializer;
+    private final DirectExecutor delegate;
+
+    InitializingExecutor(final Runnable initializer, final DirectExecutor delegate) {
+        this.initializer = initializer;
+        this.delegate = delegate;
+    }
+
+    public void execute(final Runnable command) {
+        initializer.run();
+        delegate.execute(command);
+    }
+
+    public String toString() {
+        return String.format("%s (task=%s) -> %s", super.toString(), initializer, delegate);
+    }
+}

Modified: projects/jboss-threads/trunk/main/src/main/java/org/jboss/threads/JBossExecutors.java
===================================================================
--- projects/jboss-threads/trunk/main/src/main/java/org/jboss/threads/JBossExecutors.java	2009-07-31 15:01:29 UTC (rev 91878)
+++ projects/jboss-threads/trunk/main/src/main/java/org/jboss/threads/JBossExecutors.java	2009-07-31 15:14:53 UTC (rev 91879)
@@ -32,36 +32,66 @@
 import java.security.PrivilegedAction;
 import java.security.AccessController;
 import java.security.AccessControlContext;
+import java.security.Permission;
+import java.lang.reflect.Field;
+import org.jboss.logging.Logger;
 
 /**
  *
  */
 public final class JBossExecutors {
 
+    private static final Logger THREAD_ERROR_LOGGER = Logger.getLogger("org.jboss.threads.errors");
+
     private JBossExecutors() {}
 
+    private static final RuntimePermission MODIFY_THREAD_PERMISSION = new RuntimePermission("modifyThread");
+    private static final RuntimePermission CREATE_PRIVILEGED_THREAD_PERMISSION = new RuntimePermission("createPrivilegedThreads");
+
+    private static final AccessControlContext PRIVILEGED_CONTEXT = AccessController.doPrivileged(new PrivilegedAction<AccessControlContext>() {
+        public AccessControlContext run() {
+            return AccessController.getContext();
+        }
+    });
+
     private static final DirectExecutor DIRECT_EXECUTOR = new DirectExecutor() {
         public void execute(final Runnable command) {
             command.run();
         }
+
+        public String toString() {
+            return "Direct executor";
+        }
     };
 
     private static final DirectExecutor REJECTING_EXECUTOR = new DirectExecutor() {
         public void execute(final Runnable command) {
             throw new RejectedExecutionException();
         }
+
+        public String toString() {
+            return "Rejecting executor";
+        }
     };
 
     private static final DirectExecutor DISCARDING_EXECUTOR = new DirectExecutor() {
         public void execute(final Runnable command) {
             // nothing
         }
+
+        public String toString() {
+            return "Discarding executor";
+        }
     };
 
     private static final DirectExecutorService DIRECT_EXECUTOR_SERVICE = new ProtectedDirectExecutorService(DIRECT_EXECUTOR);
     private static final DirectExecutorService REJECTING_EXECUTOR_SERVICE = new ProtectedDirectExecutorService(REJECTING_EXECUTOR);
     private static final DirectExecutorService DISCARDING_EXECUTOR_SERVICE = new ProtectedDirectExecutorService(DISCARDING_EXECUTOR);
 
+    // ==================================================
+    // DIRECT EXECUTORS
+    // ==================================================
+
     /**
      * Get the direct executor.  This executor will immediately run any task it is given, and propagate back any
      * run-time exceptions thrown.
@@ -120,58 +150,36 @@
     }
 
     /**
-     * Get a task that runs the given task through the given direct executor.
+     * Create a direct executor which runs with the privileges given by the supplied {@code AccessControlContext} instance.
      *
-     * @param executor the executor to run the task through
-     * @param task the task to run
-     * @return an encapsulating task
+     * @param delegate the executor to delegate to at the privileged level
+     * @param context the {@code AccessControlContext} to use
+     * @return the new direct executor
      */
-    public static Runnable executorTask(final DirectExecutor executor, final Runnable task) {
-        return new Runnable() {
-            public void run() {
-                executor.execute(task);
-            }
-        };
+    public static DirectExecutor privilegedExecutor(final DirectExecutor delegate, final AccessControlContext context) {
+        return new PrivilegedExecutor(delegate, context);
     }
 
     /**
-     * An executor which delegates to another executor, wrapping each task in a task wrapper.
+     * Create a direct executor which runs with the privileges given by the current access control context.
      *
-     * @param delegate the delegate executor
-     * @param taskWrapper the task wrapper
-     * @return a wrapping executor
+     * @param delegate the executor to delegate to at the privileged level
+     * @return the new direct executor
      */
-    public static Executor wrappingExecutor(final Executor delegate, final DirectExecutor taskWrapper) {
-        return new Executor() {
-            public void execute(final Runnable command) {
-                delegate.execute(executorTask(taskWrapper, command));
-            }
-        };
+    public static DirectExecutor privilegedExecutor(final DirectExecutor delegate) {
+        return privilegedExecutor(delegate, AccessController.getContext());
     }
 
     /**
-     * Create a direct executor which runs with the privileges given by the supplied {@code AccessControlContext} instance.
+     * Create an executor which executes tasks at the privilege level of this library.
+     * TODO - is this the best approach?
      *
      * @param delegate the executor to delegate to at the privileged level
-     * @param context the {@code AccessControlContext} to use
      * @return the new direct executor
      */
-    public static DirectExecutor privilegedExecutor(final DirectExecutor delegate, final AccessControlContext context) {
-        return new DirectExecutor() {
-            public void execute(final Runnable command) {
-                final SecurityManager sm = System.getSecurityManager();
-                if (sm != null) {
-                    AccessController.doPrivileged(new PrivilegedAction<Void>() {
-                        public Void run() {
-                            delegate.execute(command);
-                            return null;
-                        }
-                    }, context);
-                } else {
-                    delegate.execute(command);
-                }
-            }
-        };
+    static DirectExecutor highPrivilegeExecutor(final DirectExecutor delegate) {
+        checkAccess(CREATE_PRIVILEGED_THREAD_PERMISSION);
+        return privilegedExecutor(delegate, PRIVILEGED_CONTEXT);
     }
 
     /**
@@ -182,18 +190,7 @@
      * @return the new direct executor
      */
     public static DirectExecutor contextClassLoaderExecutor(final DirectExecutor delegate, final ClassLoader taskClassLoader) {
-        return new DirectExecutor() {
-            public void execute(final Runnable command) {
-                final Thread thr = Thread.currentThread();
-                ClassLoader old = thr.getContextClassLoader();
-                thr.setContextClassLoader(taskClassLoader);
-                try {
-                    delegate.execute(command);
-                } finally {
-                    thr.setContextClassLoader(old);
-                }
-            }
-        };
+        return new ContextClassLoaderExecutor(taskClassLoader, delegate);
     }
 
     /**
@@ -204,18 +201,7 @@
      * @return the new direct executor
      */
     public static DirectExecutor threadNameExecutor(final DirectExecutor delegate, final String newName) {
-        return new DirectExecutor() {
-            public void execute(final Runnable command) {
-                final Thread thr = Thread.currentThread();
-                final String oldName = thr.getName();
-                thr.setName(newName);
-                try {
-                    delegate.execute(command);
-                } finally {
-                    thr.setName(oldName);
-                }
-            }
-        };
+        return new ThreadNameExecutor(newName, delegate);
     }
 
     /**
@@ -226,19 +212,7 @@
      * @return the new direct executor
      */
     public static DirectExecutor threadNameNotateExecutor(final DirectExecutor delegate, final String notation) {
-        return new DirectExecutor() {
-            public void execute(final Runnable command) {
-                final Thread thr = Thread.currentThread();
-                final String oldName;
-                oldName = thr.getName();
-                thr.setName(oldName + " (" + notation + ')');
-                try {
-                    delegate.execute(command);
-                } finally {
-                    thr.setName(oldName);
-                }
-            }
-        };
+        return new ThreadNameNotatingExecutor(notation, delegate);
     }
 
     /**
@@ -248,20 +222,22 @@
      * @param log the logger to which exceptions are written at the {@code error} level
      * @return the new direct executor
      */
-    public static DirectExecutor exceptionLoggingExecutor(final DirectExecutor delegate, final Object log) {
-        return new DirectExecutor() {
-            public void execute(final Runnable command) {
-                try {
-                    delegate.execute(command);
-                } catch (Throwable t) {
-                    // todo log it
-                    // log.error(t, "Exception thrown from thread task");
-                }
-            }
-        };
+    public static DirectExecutor exceptionLoggingExecutor(final DirectExecutor delegate, final Logger log) {
+        return new ExceptionLoggingExecutor(delegate, log);
     }
 
     /**
+     * Create a direct executor which consumes and logs errors that are thrown to the default thread error category
+     * {@code "org.jboss.threads.errors"}.
+     *
+     * @param delegate the executor to delegate to
+     * @return the new direct executor
+     */
+    public static DirectExecutor exceptionLoggingExecutor(final DirectExecutor delegate) {
+        return exceptionLoggingExecutor(delegate, THREAD_ERROR_LOGGER);
+    }
+
+    /**
      * Create a direct executor which delegates tasks to the given executor, and then clears <b>all</b> thread-local
      * data after each task completes (regardless of outcome).  You must have the {@link RuntimePermission}{@code ("modifyThread")}
      * permission to use this method.
@@ -271,23 +247,68 @@
      * @throws SecurityException if the caller does not have the {@link RuntimePermission}{@code ("modifyThread")} permission
      */
     public static DirectExecutor resettingExecutor(final DirectExecutor delegate) throws SecurityException {
-        return new ResettingDirectExecutor(delegate);
+        return initializingExecutor(threadLocalResetter(), delegate);
     }
 
     /**
-     * Create an executor that executes each task in a new thread.
+     * Create an executor which runs the given initization task before running its given task.
      *
-     * @param factory the thread factory to use
-     * @return the executor
+     * @param initializer the initialization task
+     * @param delegate the delegate direct executor
+     * @return an initializing executor
      */
-    public static Executor threadFactoryExecutor(final ThreadFactory factory) {
+    public static DirectExecutor initializingExecutor(final Runnable initializer, final DirectExecutor delegate) {
+        return new InitializingExecutor(initializer, delegate);
+    }
+
+    // ==================================================
+    // EXECUTORS
+    // ==================================================
+
+    /**
+     * An executor which delegates to another executor, wrapping each task in a task wrapper.
+     *
+     * @param delegate the delegate executor
+     * @param taskWrapper the task wrapper
+     * @return a wrapping executor
+     */
+    public static Executor wrappingExecutor(final Executor delegate, final DirectExecutor taskWrapper) {
         return new Executor() {
             public void execute(final Runnable command) {
-                factory.newThread(command).start();
+                delegate.execute(executorTask(taskWrapper, command));
             }
         };
     }
 
+    /**
+     * An executor which delegates to another executor, wrapping each task in a task wrapper.
+     *
+     * @param delegate the delegate executor
+     * @param taskWrapper the task wrapper
+     * @return a wrapping executor
+     */
+    public static Executor wrappingExecutor(final WrappingExecutor delegate, final DirectExecutor taskWrapper) {
+        return new Executor() {
+            public void execute(final Runnable command) {
+                delegate.execute(command, taskWrapper);
+            }
+        };
+    }
+
+    /**
+     * Create an executor that executes each task in a new thread.
+     *
+     * @param factory the thread factory to use
+     * @return the executor
+     */
+    public static Executor threadFactoryExecutor(final ThreadFactory factory) {
+        return new ThreadFactoryExecutor(factory);
+    }
+
+    // ==================================================
+    // REJECTED EXECUTION HANDLERS
+    // ==================================================
+
     private static final RejectedExecutionHandler ABORT_POLICY = new ThreadPoolExecutor.AbortPolicy();
     private static final RejectedExecutionHandler CALLER_RUNS_POLICY = new ThreadPoolExecutor.CallerRunsPolicy();
     private static final RejectedExecutionHandler DISCARD_OLDEST_POLICY = new ThreadPoolExecutor.DiscardOldestPolicy();
@@ -348,6 +369,10 @@
         };
     }
 
+    // ==================================================
+    // PROTECTED EXECUTOR SERVICE WRAPPERS
+    // ==================================================
+
     /**
      * Wrap an executor with an {@code ExecutorService} instance which supports all the features of {@code ExecutorService}
      * except for shutting down the executor.
@@ -381,20 +406,153 @@
         return new ProtectedScheduledExecutorService(target);
     }
 
+    // ==================================================
+    // THREAD FACTORIES
+    // ==================================================
+
     /**
-     * Wrap a configurable executor with a preconfigured executor.
+     * Create a thread factory which resets all thread-local storage and delegates to the given thread factory.
+     * You must have the {@link RuntimePermission}{@code ("modifyThread")} permission to use this method.
      *
-     * @param configurableExecutor the configurable executor
-     * @param taskExecutor the direct executor to wrap tasks in, or {@code null} for none
-     * @param rejectionPolicy the rejection policy for the new executor
-     * @param handoffExecutor the handoff executor to use in the event of a rejected task
-     * @return a configured executor
+     * @param delegate the delegate thread factory
+     * @return the resetting thread factory
+     * @throws SecurityException if the caller does not have the {@link RuntimePermission}{@code ("modifyThread")}
+     * permission
      */
-    public static Executor configuredExecutor(final ConfigurableExecutor configurableExecutor, final DirectExecutor taskExecutor, final RejectionPolicy rejectionPolicy, final Executor handoffExecutor) {
-        return new Executor() {
-            public void execute(final Runnable command) {
-                configurableExecutor.execute(command, taskExecutor, rejectionPolicy, handoffExecutor);
+    public static ThreadFactory resettingThreadFactory(final ThreadFactory delegate) throws SecurityException {
+        return wrappingThreadFactory(resettingExecutor(directExecutor()), delegate);
+    }
+
+    /**
+     * Creates a thread factory which executes the thread task via the given task wrapping executor.
+     *
+     * @param taskWrapper the task wrapping executor
+     * @param delegate the delegate thread factory
+     * @return the wrapping thread factory
+     */
+    public static ThreadFactory wrappingThreadFactory(final DirectExecutor taskWrapper, final ThreadFactory delegate) {
+        return new WrappingThreadFactory(delegate, taskWrapper);
+    }
+
+    private static final Runnable TCCL_RESETTER = new Runnable() {
+        public void run() {
+            Thread.currentThread().setContextClassLoader(null);
+        }
+
+        public String toString() {
+            return "ContextClassLoader-resetting Runnable";
+        }
+    };
+
+    private static final Runnable THREAD_LOCAL_RESETTER = new ThreadLocalResetter();
+
+    private static final class ThreadLocalResetter implements Runnable {
+        private static final Field THREAD_LOCAL_MAP_FIELD;
+        private static final Field INHERITABLE_THREAD_LOCAL_MAP_FIELD;
+
+        static {
+            THREAD_LOCAL_MAP_FIELD = AccessController.doPrivileged(new PrivilegedAction<Field>() {
+                public Field run() {
+                    final Field field;
+                    try {
+                        field = Thread.class.getDeclaredField("threadLocals");
+                        field.setAccessible(true);
+                    } catch (NoSuchFieldException e) {
+                        return null;
+                    }
+                    return field;
+                }
+            });
+            INHERITABLE_THREAD_LOCAL_MAP_FIELD = AccessController.doPrivileged(new PrivilegedAction<Field>() {
+                public Field run() {
+                    final Field field;
+                    try {
+                        field = Thread.class.getDeclaredField("inheritableThreadLocals");
+                        field.setAccessible(true);
+                    } catch (NoSuchFieldException e) {
+                        return null;
+                    }
+                    return field;
+                }
+            });
+        }
+
+        private ThreadLocalResetter() {
+        }
+
+        public void run() {
+            final Thread thread = Thread.currentThread();
+            clear(thread, THREAD_LOCAL_MAP_FIELD);
+            clear(thread, INHERITABLE_THREAD_LOCAL_MAP_FIELD);
+        }
+
+        private static void clear(final Thread currentThread, final Field field) {
+            try {
+                if (field != null) field.set(currentThread, null);
+            } catch (IllegalAccessException e) {
+                // ignore
             }
+        }
+    }
+
+    private static final Runnable NULL_RUNNABLE = new NullRunnable();
+
+    // ==================================================
+    // RUNNABLES
+    // ==================================================
+
+    /**
+     * Get the null runnable which does nothing.
+     *
+     * @return the null runnable
+     */
+    public static Runnable nullRunnable() {
+        return NULL_RUNNABLE;
+    }
+
+    /**
+     * Get a {@code Runnable} which, when executed, clears the thread-local storage of the calling thread.
+     * You must have the {@link RuntimePermission}{@code ("modifyThread")}
+     * permission to use this method.
+     *
+     * @return the runnable
+     * @throws SecurityException if the caller does not have the {@link RuntimePermission}{@code ("modifyThread")}
+     * permission
+     */
+    public static Runnable threadLocalResetter() throws SecurityException {
+        checkAccess(MODIFY_THREAD_PERMISSION);
+        return THREAD_LOCAL_RESETTER;
+    }
+
+    /**
+     * Get a {@code Runnable} which, when executed, clears the thread context class loader (if the caller has sufficient
+     * privileges).
+     *
+     * @return the runnable
+     */
+    public static Runnable contextClassLoaderResetter() {
+        return TCCL_RESETTER;
+    }
+
+    /**
+     * Get a task that runs the given task through the given direct executor.
+     *
+     * @param executor the executor to run the task through
+     * @param task the task to run
+     * @return an encapsulating task
+     */
+    public static Runnable executorTask(final DirectExecutor executor, final Runnable task) {
+        return new Runnable() {
+            public void run() {
+                executor.execute(task);
+            }
         };
     }
+
+    private static void checkAccess(Permission permission) {
+        final SecurityManager sm = System.getSecurityManager();
+        if (sm != null) {
+            sm.checkPermission(permission);
+        }
+    }
 }

Modified: projects/jboss-threads/trunk/main/src/main/java/org/jboss/threads/JBossThread.java
===================================================================
--- projects/jboss-threads/trunk/main/src/main/java/org/jboss/threads/JBossThread.java	2009-07-31 15:01:29 UTC (rev 91878)
+++ projects/jboss-threads/trunk/main/src/main/java/org/jboss/threads/JBossThread.java	2009-07-31 15:14:53 UTC (rev 91879)
@@ -22,10 +22,14 @@
 
 package org.jboss.threads;
 
+import org.jboss.logging.Logger;
+
 /**
  *
  */
 public final class JBossThread extends Thread {
+    private static final Logger log = Logger.getLogger(JBossThread.class);
+
     private final InterruptHandler[] interruptHandlers;
 
     public JBossThread(final InterruptHandler[] handlers, final ThreadGroup group, final Runnable target, final String name, final long stackSize) {
@@ -46,18 +50,18 @@
                 for (InterruptHandler interruptHandler : interruptHandlers) try {
                     interruptHandler.handleInterrupt(this);
                 } catch (Throwable t) {
-                    // must ignore
+                    log.errorf(t, "Interrupt handler %s threw an exception", interruptHandler);
                 }
             }
         }
     }
 
     public void run() {
-        // todo log start
+        log.tracef("Starting thread %s", this);
         try {
             super.run();
         } finally {
-            // todo log end
+            log.tracef("Terminating thread %s", this);
         }
     }
 }

Added: projects/jboss-threads/trunk/main/src/main/java/org/jboss/threads/NullRunnable.java
===================================================================
--- projects/jboss-threads/trunk/main/src/main/java/org/jboss/threads/NullRunnable.java	                        (rev 0)
+++ projects/jboss-threads/trunk/main/src/main/java/org/jboss/threads/NullRunnable.java	2009-07-31 15:14:53 UTC (rev 91879)
@@ -0,0 +1,30 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.threads;
+
+final class NullRunnable implements Runnable {
+
+    public void run() {
+        // do nothing
+    }
+}

Added: projects/jboss-threads/trunk/main/src/main/java/org/jboss/threads/PrivilegedExecutor.java
===================================================================
--- projects/jboss-threads/trunk/main/src/main/java/org/jboss/threads/PrivilegedExecutor.java	                        (rev 0)
+++ projects/jboss-threads/trunk/main/src/main/java/org/jboss/threads/PrivilegedExecutor.java	2009-07-31 15:14:53 UTC (rev 91879)
@@ -0,0 +1,56 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.threads;
+
+import java.security.AccessControlContext;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+
+class PrivilegedExecutor implements DirectExecutor {
+
+    private final DirectExecutor delegate;
+    private final AccessControlContext context;
+
+    PrivilegedExecutor(final DirectExecutor delegate, final AccessControlContext context) {
+        this.delegate = delegate;
+        this.context = context;
+    }
+
+    public void execute(final Runnable command) {
+        final SecurityManager sm = System.getSecurityManager();
+        if (sm != null) {
+            AccessController.doPrivileged(new PrivilegedAction<Void>() {
+                public Void run() {
+                    delegate.execute(command);
+                    return null;
+                }
+            }, context);
+        } else {
+            delegate.execute(command);
+        }
+    }
+
+    public String toString() {
+        return String.format("%s (for %s) -> %s", super.toString(), context, delegate);
+    }
+}

Modified: projects/jboss-threads/trunk/main/src/main/java/org/jboss/threads/ProtectedExecutorService.java
===================================================================
--- projects/jboss-threads/trunk/main/src/main/java/org/jboss/threads/ProtectedExecutorService.java	2009-07-31 15:01:29 UTC (rev 91878)
+++ projects/jboss-threads/trunk/main/src/main/java/org/jboss/threads/ProtectedExecutorService.java	2009-07-31 15:14:53 UTC (rev 91879)
@@ -68,4 +68,8 @@
     public static ExecutorService directExecutorService() {
         return new ProtectedExecutorService(JBossExecutors.directExecutor());
     }
+
+    public String toString() {
+        return String.format("%s -> %s", super.toString(), delegate);
+    }
 }

Deleted: projects/jboss-threads/trunk/main/src/main/java/org/jboss/threads/QueuelessThreadPoolExecutor.java
===================================================================
--- projects/jboss-threads/trunk/main/src/main/java/org/jboss/threads/QueuelessThreadPoolExecutor.java	2009-07-31 15:01:29 UTC (rev 91878)
+++ projects/jboss-threads/trunk/main/src/main/java/org/jboss/threads/QueuelessThreadPoolExecutor.java	2009-07-31 15:14:53 UTC (rev 91879)
@@ -1,56 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors.
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-
-package org.jboss.threads;
-
-import java.util.concurrent.Executor;
-import java.util.concurrent.SynchronousQueue;
-import java.util.concurrent.ThreadPoolExecutor;
-import java.util.concurrent.TimeUnit;
-
-/**
- * Create a queueless thread pool executor.
- */
-public final class QueuelessThreadPoolExecutor extends ThreadPoolExecutor implements ConfigurableExecutor {
-
-    /**
-     * Construct a new instance.
-     *
-     * @param keepAliveTime the thread keepalive time
-     * @param unit the time unit
-     */
-    public QueuelessThreadPoolExecutor(final long keepAliveTime, final TimeUnit unit) {
-        super(0, Integer.MAX_VALUE, keepAliveTime, unit, new SynchronousQueue<Runnable>());
-    }
-
-    /**
-     * Execute a task.  Tasks on a queueless executor are never rejected (unless the pool is shut down).
-     *
-     * @param task the task to execute
-     * @param taskExecutor the direct executor to use, or {@code null} to execute the task as-is
-     * @param policy the rejection policy (ignored)
-     * @param handoffExecutor the handoff executor (ignored)
-     */
-    public void execute(final Runnable task, final DirectExecutor taskExecutor, final RejectionPolicy policy, final Executor handoffExecutor) {
-        execute(taskExecutor == null || taskExecutor == JBossExecutors.directExecutor() ? task : JBossExecutors.executorTask(taskExecutor, task));
-    }
-}

Deleted: projects/jboss-threads/trunk/main/src/main/java/org/jboss/threads/ResettingDirectExecutor.java
===================================================================
--- projects/jboss-threads/trunk/main/src/main/java/org/jboss/threads/ResettingDirectExecutor.java	2009-07-31 15:01:29 UTC (rev 91878)
+++ projects/jboss-threads/trunk/main/src/main/java/org/jboss/threads/ResettingDirectExecutor.java	2009-07-31 15:14:53 UTC (rev 91879)
@@ -1,97 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors.
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-
-package org.jboss.threads;
-
-import java.lang.reflect.Field;
-import java.security.AccessController;
-import java.security.PrivilegedAction;
-
-/**
- * A direct executor which resets the thread-local maps after every task (if possible).
- */
-final class ResettingDirectExecutor implements DirectExecutor {
-    private final DirectExecutor delegate;
-
-    private static final Field THREAD_LOCAL_MAP_FIELD;
-    private static final Field INHERITABLE_THREAD_LOCAL_MAP_FIELD;
-    private static final RuntimePermission MODIFY_THREAD_PERMISSION = new RuntimePermission("modifyThread");
-
-    static {
-        THREAD_LOCAL_MAP_FIELD = AccessController.doPrivileged(new PrivilegedAction<Field>() {
-            public Field run() {
-                final Field field;
-                try {
-                    field = Thread.class.getDeclaredField("threadLocals");
-                    field.setAccessible(true);
-                } catch (NoSuchFieldException e) {
-                    return null;
-                }
-                return field;
-            }
-        });
-        INHERITABLE_THREAD_LOCAL_MAP_FIELD = AccessController.doPrivileged(new PrivilegedAction<Field>() {
-            public Field run() {
-                final Field field;
-                try {
-                    field = Thread.class.getDeclaredField("inheritableThreadLocals");
-                    field.setAccessible(true);
-                } catch (NoSuchFieldException e) {
-                    return null;
-                }
-                return field;
-            }
-        });
-    }
-
-    /**
-     * Construct a new instance.
-     *
-     * @param delegate the executor which will actually execute the task
-     */
-    ResettingDirectExecutor(DirectExecutor delegate) {
-        final SecurityManager sm = System.getSecurityManager();
-        if (sm != null) {
-            sm.checkPermission(MODIFY_THREAD_PERMISSION);
-        }
-        this.delegate = delegate;
-    }
-
-    private static void clear(final Thread currentThread, final Field field) {
-        try {
-            field.set(currentThread, null);
-        } catch (IllegalAccessException e) {
-            // ignore
-        }
-    }
-
-    /** {@inheritDoc} */
-    public void execute(Runnable command) {
-        try {
-            delegate.execute(command);
-        } finally {
-            final Thread thread = Thread.currentThread();
-            clear(thread, THREAD_LOCAL_MAP_FIELD);
-            clear(thread, INHERITABLE_THREAD_LOCAL_MAP_FIELD);
-        }
-    }
-}

Added: projects/jboss-threads/trunk/main/src/main/java/org/jboss/threads/ThreadFactoryExecutor.java
===================================================================
--- projects/jboss-threads/trunk/main/src/main/java/org/jboss/threads/ThreadFactoryExecutor.java	                        (rev 0)
+++ projects/jboss-threads/trunk/main/src/main/java/org/jboss/threads/ThreadFactoryExecutor.java	2009-07-31 15:14:53 UTC (rev 91879)
@@ -0,0 +1,48 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.threads;
+
+import java.util.concurrent.Executor;
+import java.util.concurrent.ThreadFactory;
+import java.util.concurrent.RejectedExecutionException;
+
+class ThreadFactoryExecutor implements Executor {
+
+    private final ThreadFactory factory;
+
+    ThreadFactoryExecutor(final ThreadFactory factory) {
+        this.factory = factory;
+    }
+
+    public void execute(final Runnable command) {
+        final Thread thread = factory.newThread(command);
+        if (thread == null) {
+            throw new RejectedExecutionException("No threads can be created");
+        }
+        thread.start();
+    }
+
+    public String toString() {
+        return String.format("%s (%s)", super.toString(), factory);
+    }
+}

Added: projects/jboss-threads/trunk/main/src/main/java/org/jboss/threads/ThreadNameExecutor.java
===================================================================
--- projects/jboss-threads/trunk/main/src/main/java/org/jboss/threads/ThreadNameExecutor.java	                        (rev 0)
+++ projects/jboss-threads/trunk/main/src/main/java/org/jboss/threads/ThreadNameExecutor.java	2009-07-31 15:14:53 UTC (rev 91879)
@@ -0,0 +1,49 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.threads;
+
+class ThreadNameExecutor implements DirectExecutor {
+
+    private final String newName;
+    private final DirectExecutor delegate;
+
+    ThreadNameExecutor(final String newName, final DirectExecutor delegate) {
+        this.newName = newName;
+        this.delegate = delegate;
+    }
+
+    public void execute(final Runnable command) {
+        final Thread thr = Thread.currentThread();
+        final String oldName = thr.getName();
+        thr.setName(newName);
+        try {
+            delegate.execute(command);
+        } finally {
+            thr.setName(oldName);
+        }
+    }
+
+    public String toString() {
+        return String.format("%s name=\"%s\" -> %s", super.toString(), newName, delegate);
+    }
+}

Added: projects/jboss-threads/trunk/main/src/main/java/org/jboss/threads/ThreadNameNotatingExecutor.java
===================================================================
--- projects/jboss-threads/trunk/main/src/main/java/org/jboss/threads/ThreadNameNotatingExecutor.java	                        (rev 0)
+++ projects/jboss-threads/trunk/main/src/main/java/org/jboss/threads/ThreadNameNotatingExecutor.java	2009-07-31 15:14:53 UTC (rev 91879)
@@ -0,0 +1,50 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.threads;
+
+class ThreadNameNotatingExecutor implements DirectExecutor {
+
+    private final String notation;
+    private final DirectExecutor delegate;
+
+    ThreadNameNotatingExecutor(final String notation, final DirectExecutor delegate) {
+        this.notation = notation;
+        this.delegate = delegate;
+    }
+
+    public void execute(final Runnable command) {
+        final Thread thr = Thread.currentThread();
+        final String oldName;
+        oldName = thr.getName();
+        thr.setName(oldName + " (" + notation + ')');
+        try {
+            delegate.execute(command);
+        } finally {
+            thr.setName(oldName);
+        }
+    }
+
+    public String toString() {
+        return String.format("%s notation=\"%s\" -> %s", super.toString(), notation, delegate);
+    }
+}

Added: projects/jboss-threads/trunk/main/src/main/java/org/jboss/threads/ThreadPool.java
===================================================================
--- projects/jboss-threads/trunk/main/src/main/java/org/jboss/threads/ThreadPool.java	                        (rev 0)
+++ projects/jboss-threads/trunk/main/src/main/java/org/jboss/threads/ThreadPool.java	2009-07-31 15:14:53 UTC (rev 91879)
@@ -0,0 +1,207 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.threads;
+
+import java.util.concurrent.ThreadFactory;
+import java.util.concurrent.RejectedExecutionException;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantLock;
+import java.util.concurrent.locks.Condition;
+
+/**
+ * A queueless thread pool.  If one or more threads are waiting for work when a task is submitted, it will be used.
+ * Otherwise, if fewer than the maximum threads are started, a new thread is created.
+ */
+public final class ThreadPool {
+
+    private final ThreadFactory threadFactory;
+
+    private volatile long idleTimeout;
+    private int maxThreads;
+    private int runningThreads;
+
+    private Task parkedTask;
+    private final Lock poolLock = new ReentrantLock();
+    // signal when parking a task
+    private final Condition park = poolLock.newCondition();
+    // signal when unparking a task
+    private final Condition unpark = poolLock.newCondition();
+
+    private State state = State.RUNNING;
+
+    private enum State {
+        RUNNING,
+        KILL,
+    }
+
+    public ThreadPool(final ThreadFactory threadFactory) {
+        this.threadFactory = threadFactory;
+        idleTimeout = 30000L;
+        maxThreads = 20;
+        runningThreads = 0;
+    }
+
+    public void executeBlocking(final Runnable runnable, final DirectExecutor taskExecutor) throws InterruptedException {
+        if (runnable == null) {
+            throw new NullPointerException("runnable is null");
+        }
+        final Lock poolLock = this.poolLock;
+        final Condition park = this.park;
+        final Condition unpark = this.unpark;
+        Task task;
+        poolLock.lockInterruptibly();
+        try {
+            for (;;) {
+                if (state == State.KILL) {
+                    throw new RejectedExecutionException("Thread pool is shut down");
+                } else if ((task = parkedTask) != null) {
+                    parkedTask = null;
+                    unpark.signal();
+                    break;
+                } else {
+                    final int runningThreads = this.runningThreads;
+                    if (runningThreads < maxThreads) {
+                        task = new Task(runnable, taskExecutor);
+                        final ThreadFactory threadFactory = this.threadFactory;
+                        final Thread newThread = threadFactory.newThread(task);
+                        if (newThread == null) {
+                            throw new RejectedExecutionException("Thread factory " + threadFactory + " will not create a thread");
+                        }
+                        newThread.start();
+                        this.runningThreads = runningThreads + 1;
+                        return;
+                    } else {
+                        park.await();
+                    }
+                }
+            }
+        } finally {
+            poolLock.unlock();
+        }
+        synchronized (task) {
+            task.runnable = runnable;
+            task.taskExecutor = taskExecutor;
+            task.notify();
+        }
+    }
+
+    private final class Task implements Runnable {
+
+        /**
+         * Protected by {@code this}.
+         */
+        private Runnable runnable;
+        private DirectExecutor taskExecutor;
+
+        Task(final Runnable runnable, final DirectExecutor taskExecutor) {
+            synchronized (this) {
+                this.runnable = runnable;
+                this.taskExecutor = taskExecutor;
+            }
+        }
+
+        public void run() {
+            final Lock poolLock = ThreadPool.this.poolLock;
+            Runnable runnable;
+            DirectExecutor taskExecutor;
+            try {
+                synchronized (this) {
+                    runnable = this.runnable;
+                    taskExecutor = this.taskExecutor;
+                    this.runnable = null;
+                    this.taskExecutor = null;
+                }
+                long idleSince = runnable == null ? System.currentTimeMillis() : Long.MAX_VALUE;
+                for (;;) {
+                    while (runnable == null) {
+                        // no task; park
+                        poolLock.lock();
+                        try {
+                            if (state == State.KILL) {
+                                return;
+                            }
+                            // wait for the spot to open
+                            Task task;
+                            while ((task = parkedTask) != null && task != this) {
+                                try {
+                                    final long remaining = idleTimeout - (System.currentTimeMillis() - idleSince);
+                                    if (remaining < 0L) {
+                                        // idle timeout; don't bother finishing parking
+                                        return;
+                                    }
+                                    unpark.await(remaining, TimeUnit.MILLISECONDS);
+                                } catch (InterruptedException e) {
+                                    if (state == State.KILL) {
+                                        return;
+                                    }
+                                }
+                            }
+                            parkedTask = this;
+                        } finally {
+                            poolLock.unlock();
+                        }
+                        // parked!  Now just wait for a task to show up
+                        synchronized (this) {
+                            while ((runnable = this.runnable) == null) {
+                                try {
+                                    final long remaining = idleTimeout - (System.currentTimeMillis() - idleSince);
+                                    if (remaining < 0L) {
+                                        // idle timeout; unpark and return
+                                        return;
+                                    }
+                                    wait(remaining);
+                                } catch (InterruptedException e) {
+                                    break;
+                                }
+                            }
+                            taskExecutor = this.taskExecutor;
+                            this.runnable = null;
+                            this.taskExecutor = null;
+                        }
+                    }
+                    (taskExecutor == null ? JBossExecutors.directExecutor() : taskExecutor).execute(runnable);
+                    synchronized (this) {
+                        runnable = this.runnable;
+                        taskExecutor = this.taskExecutor;
+                        this.runnable = null;
+                        this.taskExecutor = null;
+                    }
+                    if (runnable == null) idleSince = System.currentTimeMillis();
+                }
+            } finally {
+                poolLock.lock();
+                try {
+                    // If this task is parked, unpark it so someone else can get in there
+                    if (parkedTask == this) {
+                        parkedTask = null;
+                        unpark.signal();
+                    }
+                    runningThreads--;
+                } finally {
+                    poolLock.unlock();
+                }
+            }
+        }
+    }
+}

Added: projects/jboss-threads/trunk/main/src/main/java/org/jboss/threads/WrappingExecutor.java
===================================================================
--- projects/jboss-threads/trunk/main/src/main/java/org/jboss/threads/WrappingExecutor.java	                        (rev 0)
+++ projects/jboss-threads/trunk/main/src/main/java/org/jboss/threads/WrappingExecutor.java	2009-07-31 15:14:53 UTC (rev 91879)
@@ -0,0 +1,32 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.threads;
+
+import java.util.concurrent.RejectedExecutionException;
+
+/**
+ * An executor which runs a task within the given direct executor.
+ */
+public interface WrappingExecutor {
+    void execute(Runnable task, DirectExecutor directExecutor) throws RejectedExecutionException;
+}

Added: projects/jboss-threads/trunk/main/src/main/java/org/jboss/threads/WrappingThreadFactory.java
===================================================================
--- projects/jboss-threads/trunk/main/src/main/java/org/jboss/threads/WrappingThreadFactory.java	                        (rev 0)
+++ projects/jboss-threads/trunk/main/src/main/java/org/jboss/threads/WrappingThreadFactory.java	2009-07-31 15:14:53 UTC (rev 91879)
@@ -0,0 +1,48 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.threads;
+
+import java.util.concurrent.ThreadFactory;
+
+class WrappingThreadFactory implements ThreadFactory {
+
+    private final ThreadFactory delegate;
+    private final DirectExecutor taskWrapper;
+
+    WrappingThreadFactory(final ThreadFactory delegate, final DirectExecutor taskWrapper) {
+        this.delegate = delegate;
+        this.taskWrapper = taskWrapper;
+    }
+
+    public Thread newThread(final Runnable r) {
+        return delegate.newThread(new Runnable() {
+            public void run() {
+                taskWrapper.execute(r);
+            }
+        });
+    }
+
+    public String toString() {
+        return String.format("%s (%s) -> %s", super.toString(), taskWrapper, delegate);
+    }
+}




More information about the jboss-cvs-commits mailing list