[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