pax_global_header00006660000000000000000000000064132527436010014515gustar00rootroot0000000000000052 comment=e09c8dfd1b7162bc497dd4df8af507eb1ad7e21d jboss-threads-2.3.2.Final/000077500000000000000000000000001325274360100153215ustar00rootroot00000000000000jboss-threads-2.3.2.Final/.gitignore000066400000000000000000000000751325274360100173130ustar00rootroot00000000000000target .classpath .project .settings .idea *.iml *.ipr *.iws jboss-threads-2.3.2.Final/LICENSE.txt000066400000000000000000000236761325274360100171620ustar00rootroot00000000000000 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS jboss-threads-2.3.2.Final/pom.xml000066400000000000000000000110071325274360100166350ustar00rootroot00000000000000 4.0.0 org.jboss.threads jboss-threads jar 2.3.2.Final JBoss Threads org.jboss jboss-parent 20 Jira https://issues.jboss.org/browse/JBTHR Apache License 2.0 http://www.apache.org/licenses/LICENSE-2.0.txt INFO org.jboss.logging jboss-logging-annotations 2.0.2.Final provided org.jboss.logging jboss-logging-processor 2.0.2.Final provided org.jboss.logging jboss-logging 3.3.1.Final org.wildfly.common wildfly-common 1.3.0.Final junit junit 4.12 test org.jboss.logmanager jboss-logmanager 2.0.7.Final test ${project.basedir} LICENSE.txt META-INF false src/main/java true **/*.properties maven-compiler-plugin maven-source-plugin maven-surefire-plugin test.level ${test.level} java.util.logging.manager org.jboss.logmanager.LogManager always jboss-threads-2.3.2.Final/src/000077500000000000000000000000001325274360100161105ustar00rootroot00000000000000jboss-threads-2.3.2.Final/src/main/000077500000000000000000000000001325274360100170345ustar00rootroot00000000000000jboss-threads-2.3.2.Final/src/main/java/000077500000000000000000000000001325274360100177555ustar00rootroot00000000000000jboss-threads-2.3.2.Final/src/main/java/org/000077500000000000000000000000001325274360100205445ustar00rootroot00000000000000jboss-threads-2.3.2.Final/src/main/java/org/jboss/000077500000000000000000000000001325274360100216645ustar00rootroot00000000000000jboss-threads-2.3.2.Final/src/main/java/org/jboss/threads/000077500000000000000000000000001325274360100233165ustar00rootroot00000000000000jboss-threads-2.3.2.Final/src/main/java/org/jboss/threads/ArrayQueue.java000066400000000000000000000074131325274360100262510ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2017 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.threads; import java.util.AbstractQueue; import java.util.Iterator; import java.util.NoSuchElementException; import java.util.Queue; import java.util.Arrays; import java.util.ConcurrentModificationException; import org.wildfly.common.Assert; /** * A simple array-backed queue with a fixed size. */ public final class ArrayQueue extends AbstractQueue implements Queue { private final E[] elements; // elements are added at head private int head; // elements are removed at tail private int tail; private int modCnt; @SuppressWarnings({ "unchecked" }) public ArrayQueue(final int capacity) { elements = (E[]) new Object[capacity]; } public Iterator iterator() { return new Iterator() { private int pos = 0; private int size = size(); private final int modIdx = modCnt; public boolean hasNext() { if (modCnt != modIdx) { throw Messages.msg.concurrentModification(); } return pos < size; } public E next() { if (modCnt != modIdx) { throw Messages.msg.concurrentModification(); } final int pos = this.pos; if (pos >= size) { throw Messages.msg.noSuchElement(); } final E[] elements = ArrayQueue.this.elements; final E value = elements[(tail + pos) % elements.length]; this.pos = pos + 1; return value; } public void remove() { throw Assert.unsupported(); } }; } public boolean isEmpty() { return elements[tail] == null; } public int size() { final int head = this.head; final int tail = this.tail; final E[] elements = this.elements; if (elements[tail] == null) { return 0; } else if (head > tail) { return head - tail; } else { return head + elements.length - tail; } } public boolean offer(final E e) { Assert.checkNotNullParam("e", e); final int head = this.head; final E[] elements = this.elements; final int len = elements.length; if (elements[head] != null) { return false; } else { elements[head] = e; this.head = (head + 1) % len; modCnt++; return true; } } public E poll() { final int tail = this.tail; final E[] elements = this.elements; final E value = elements[tail]; if (value != null) { modCnt++; elements[tail] = null; this.tail = (tail + 1) % elements.length; } return value; } public E peek() { final int tail = this.tail; return tail == -1 ? null : elements[tail]; } public void clear() { Arrays.fill(elements, null); modCnt++; tail = head = 0; } } jboss-threads-2.3.2.Final/src/main/java/org/jboss/threads/AsyncCancellable.java000066400000000000000000000026471325274360100273550ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2017 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.threads; /** * An interface which supports asynchronous cancellation. * * @author David M. Lloyd */ public interface AsyncCancellable { /** * Handle an asynchronous cancellation. Does not block, and may be called more than once; * in particular, this method may be re-invoked to set the {@code interruptionDesired} flag * even if it has already been called without that flag set before. Otherwise, this method is * idempotent, and thus may be called more than once without additional effect. * * @param interruptionDesired {@code true} if interruption of threads is desired */ void asyncCancel(boolean interruptionDesired); } jboss-threads-2.3.2.Final/src/main/java/org/jboss/threads/AsyncFuture.java000066400000000000000000000163731325274360100264430ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2017 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.threads; import java.util.concurrent.CancellationException; import java.util.concurrent.ExecutionException; import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; /** * This interface represents the result of an asynchronous future task, which provides all the features * of {@link Future} while also adding several additional convenience methods and the ability to add asynchronous * callbacks. * * @author David M. Lloyd */ public interface AsyncFuture extends Future, AsyncCancellable { /** * Wait if necessary for this operation to complete, returning the outcome. The outcome will be one of * {@link Status#COMPLETE}, {@link Status#CANCELLED}, or {@link Status#FAILED}. * * @return the outcome * @throws InterruptedException if execution was interrupted while waiting */ Status await() throws InterruptedException; /** * Wait if necessary for this operation to complete, returning the outcome, which may include {@link Status#WAITING} if * the timeout expires before the operation completes. * * @param timeout the maximum time to wait * @param unit the time unit of the timeout argument * @return the outcome * @throws InterruptedException if execution was interrupted while waiting */ Status await(long timeout, TimeUnit unit) throws InterruptedException; /** * Waits (uninterruptibly) if necessary for the computation to complete, and then retrieves the result. * * @return the computed result * @throws CancellationException if the computation was cancelled * @throws ExecutionException if the computation threw an exception */ T getUninterruptibly() throws CancellationException, ExecutionException; /** * Waits (uninterruptibly) if necessary for at most the given time for the computation to complete, and then * retrieves the result, if available. * * @param timeout the maximum time to wait * @param unit the time unit of the timeout argument * @return the computed result * @throws CancellationException if the computation was cancelled * @throws ExecutionException if the computation threw an exception * @throws TimeoutException if the wait timed out */ T getUninterruptibly(long timeout, TimeUnit unit) throws CancellationException, ExecutionException, TimeoutException; /** * Wait (uninterruptibly) if necessary for this operation to complete, returning the outcome. The outcome will be one of * {@link Status#COMPLETE}, {@link Status#CANCELLED}, or {@link Status#FAILED}. * * @return the outcome */ Status awaitUninterruptibly(); /** * Wait if necessary for this operation to complete, returning the outcome, which may include {@link Status#WAITING} if * the timeout expires before the operation completes. * * @param timeout the maximum time to wait * @param unit the time unit of the timeout argument * @return the outcome */ Status awaitUninterruptibly(long timeout, TimeUnit unit); /** * Get (poll) the current status of the asynchronous operation. * * @return the current status */ Status getStatus(); /** * Add an asynchronous listener to be called when this operation completes. * * @param listener the listener to add * @param attachment the attachment to pass in * @param the attachment type */ void addListener(Listener listener, A attachment); /** * Synchronously cancel a task, blocking uninterruptibly until it is known whether such cancellation was * successful. Note that the {@link Future#cancel(boolean)} is somewhat unclear about blocking semantics. * It is recommended to use {@link #asyncCancel(boolean)} instead. * * @param interruptionDesired if interruption is desired (if available) * @return {@code true} if cancel succeeded, {@code false} otherwise */ boolean cancel(boolean interruptionDesired); /** {@inheritDoc} */ void asyncCancel(boolean interruptionDesired); /** * The possible statuses of an {@link AsyncFuture}. */ enum Status { /** * The operation is still in progress. */ WAITING, /** * The operation has completed successfully. */ COMPLETE, /** * The operation was cancelled before it completed. */ CANCELLED, /** * The operation has failed with some exception. */ FAILED, ; } /** * A listener for an asynchronous future computation result. Each listener method is passed the * {@link AsyncFuture} which it was added to, as well as the {@code attachment} which was passed in to * {@link AsyncFuture#addListener(Listener, Object)}. * * @param the future type * @param the attachment type */ interface Listener extends java.util.EventListener { /** * Handle a successful computation result. * * @param future the future * @param attachment the attachment */ void handleComplete(AsyncFuture future, A attachment); /** * Handle a failure result. * * @param future the future * @param cause the reason for the failure * @param attachment the attachment */ void handleFailed(AsyncFuture future, Throwable cause, A attachment); /** * Handle a cancellation result. * * @param future the future * @param attachment the attachment */ void handleCancelled(AsyncFuture future, A attachment); } /** * An abstract base class for an implementation of the {@code Listener} interface. The implementation * methods do nothing unless overridden. * * @param the future type * @param the attachment type */ abstract class AbstractListener implements Listener { /** {@inheritDoc} */ public void handleComplete(final AsyncFuture future, final A attachment) { } /** {@inheritDoc} */ public void handleFailed(final AsyncFuture future, final Throwable cause, final A attachment) { } /** {@inheritDoc} */ public void handleCancelled(final AsyncFuture future, final A attachment) { } } } jboss-threads-2.3.2.Final/src/main/java/org/jboss/threads/AsyncFutureTask.java000066400000000000000000000300221325274360100272510ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2017 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.threads; import java.util.ArrayList; import java.util.List; import java.util.concurrent.CancellationException; import java.util.concurrent.ExecutionException; import java.util.concurrent.Executor; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; import org.wildfly.common.Assert; /** * A base class for implementing asynchronous tasks. This class implements * {@link java.util.concurrent.Future Future} as well as {@link AsyncFuture}, and * is approximately equivalent to {@link java.util.concurrent.FutureTask}, however it * does not implement {@link Runnable} and is somewhat more flexible. * * @author David M. Lloyd */ public abstract class AsyncFutureTask implements AsyncFuture { private final Executor executor; private AsyncFuture.Status status; private Object result; private List> listeners; private final class Reg implements Runnable { private final AsyncFuture.Listener listener; private final A attachment; private Reg(final AsyncFuture.Listener listener, final A attachment) { this.listener = listener; this.attachment = attachment; } public void run() { switch (getStatus()) { case CANCELLED: listener.handleCancelled(AsyncFutureTask.this, attachment); break; case COMPLETE: listener.handleComplete(AsyncFutureTask.this, attachment); break; case FAILED: listener.handleFailed(AsyncFutureTask.this, (Throwable) result, attachment); } } } /** * Construct a new instance. * * @param executor the executor to use for asynchronous notifications */ protected AsyncFutureTask(final Executor executor) { this.executor = executor; status = AsyncFuture.Status.WAITING; } /** * Set the successful result of this operation. Once a result is set, calls to this * or the other {@code set*()} methods are ignored. * * @param result the result * @return {@code true} if the result was successfully set, or {@code false} if a result was already set */ protected final boolean setResult(final T result) { List> list; synchronized (this) { if (status == AsyncFuture.Status.WAITING) { this.result = result; status = AsyncFuture.Status.COMPLETE; notifyAll(); list = listeners; listeners = null; } else { return false; } } if (list != null) for (Reg reg : list) { safeExecute(reg); } return true; } /** * Set the cancelled result of this operation. Once a result is set, calls to this * or the other {@code set*()} methods are ignored. * * @return {@code true} if the result was successfully set, or {@code false} if a result was already set */ protected final boolean setCancelled() { List> list; synchronized (this) { if (status == AsyncFuture.Status.WAITING) { status = AsyncFuture.Status.CANCELLED; notifyAll(); list = listeners; listeners = null; } else { return false; } } if (list != null) for (Reg reg : list) { safeExecute(reg); } return true; } /** * Set the failure result of this operation. Once a result is set, calls to this * or the other {@code set*()} methods are ignored. * * @param cause the cause of failure * @return {@code true} if the result was successfully set, or {@code false} if a result was already set */ protected final boolean setFailed(final Throwable cause) { List> list; synchronized (this) { if (status == AsyncFuture.Status.WAITING) { status = AsyncFuture.Status.FAILED; result = cause; notifyAll(); list = listeners; listeners = null; } else { return false; } } if (list != null) for (Reg reg : list) { safeExecute(reg); } return true; } private void safeExecute(final Reg reg) { try { executor.execute(reg); } catch (Throwable t) { // todo log it } } /** * Cancel this task. The default implementation of this method does nothing; if the * task support asynchronous cancel, this method may be overridden to implement it. The * implementation may choose to support or disregard the {@code interruptionDesired} flag. * Implementations are allowed to interrupt threads associated with tasks even if the flag is * {@code false}; likewise, implementations may choose not to interrupt threads even if the * flag is {@code true}. * * @param interruptionDesired {@code true} if interruption of threads is desired */ public void asyncCancel(final boolean interruptionDesired) { } /** {@inheritDoc} */ public final Status await() throws InterruptedException { synchronized (this) { while (status == Status.WAITING) { wait(); } return status; } } /** {@inheritDoc} */ public final Status await(final long timeout, final TimeUnit unit) throws InterruptedException { long remaining = unit.toNanos(timeout); long now = System.nanoTime(); Status status; synchronized (this) { for (;;) { status = this.status; if (remaining <= 0L || status != Status.WAITING) { return status; } wait(remaining / 1_000_000L, (int) (remaining % 1_000_000)); remaining -= -now + (now = System.nanoTime()); } } } /** {@inheritDoc} */ public final Status awaitUninterruptibly() { synchronized (this) { boolean intr = Thread.interrupted(); try { while (status == Status.WAITING) try { wait(); } catch (InterruptedException e) { intr = true; } } finally { if (intr) { Thread.currentThread().interrupt(); } } return status; } } /** {@inheritDoc} */ public final Status awaitUninterruptibly(final long timeout, final TimeUnit unit) { long remaining = unit.toNanos(timeout); long now = System.nanoTime(); Status status; boolean intr = Thread.interrupted(); try { synchronized (this) { for (;;) { status = this.status; if (remaining <= 0L || status != Status.WAITING) { return status; } try { wait(remaining / 1_000_000L, (int) (remaining % 1_000_000)); } catch (InterruptedException e) { intr = true; } remaining -= -now + (now = System.nanoTime()); } } } finally { if (intr) { Thread.currentThread().interrupt(); } } } /** {@inheritDoc} */ @SuppressWarnings({ "unchecked" }) public final T get() throws InterruptedException, ExecutionException { synchronized (AsyncFutureTask.this) { final Status status = await(); switch (status) { case CANCELLED: throw Messages.msg.operationCancelled(); case FAILED: throw Messages.msg.operationFailed((Throwable) result); case COMPLETE: return (T) result; default: throw Assert.impossibleSwitchCase(status); } } } /** {@inheritDoc} */ @SuppressWarnings({ "unchecked" }) public final T get(final long timeout, final TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException { synchronized (AsyncFutureTask.this) { final Status status = await(timeout, unit); switch (status) { case CANCELLED: throw Messages.msg.operationCancelled(); case FAILED: throw Messages.msg.operationFailed((Throwable) result); case COMPLETE: return (T) result; case WAITING: throw Messages.msg.operationTimedOut(); default: throw Assert.impossibleSwitchCase(status); } } } /** {@inheritDoc} */ @SuppressWarnings({ "unchecked" }) public final T getUninterruptibly() throws CancellationException, ExecutionException { synchronized (AsyncFutureTask.this) { final Status status = awaitUninterruptibly(); switch (status) { case CANCELLED: throw Messages.msg.operationCancelled(); case FAILED: throw Messages.msg.operationFailed((Throwable) result); case COMPLETE: return (T) result; default: throw Assert.impossibleSwitchCase(status); } } } /** {@inheritDoc} */ @SuppressWarnings({ "unchecked" }) public final T getUninterruptibly(final long timeout, final TimeUnit unit) throws CancellationException, ExecutionException, TimeoutException { synchronized (AsyncFutureTask.this) { final Status status = awaitUninterruptibly(timeout, unit); switch (status) { case CANCELLED: throw Messages.msg.operationCancelled(); case FAILED: throw Messages.msg.operationFailed((Throwable) result); case COMPLETE: return (T) result; case WAITING: throw Messages.msg.operationTimedOut(); default: throw Assert.impossibleSwitchCase(status); } } } /** {@inheritDoc} */ public final Status getStatus() { synchronized (AsyncFutureTask.this) { return status; } } /** {@inheritDoc} */ public final void addListener(final Listener listener, final A attachment) { synchronized (AsyncFutureTask.this) { final Reg reg = new Reg(listener, attachment); if (status == Status.WAITING) { if (listeners == null) { listeners = new ArrayList>(); } listeners.add(reg); } else { safeExecute(reg); } } } /** {@inheritDoc} */ public final boolean cancel(final boolean interruptionDesired) { asyncCancel(interruptionDesired); return awaitUninterruptibly() == Status.CANCELLED; } /** {@inheritDoc} */ public final boolean isCancelled() { return getStatus() == Status.CANCELLED; } /** {@inheritDoc} */ public final boolean isDone() { return getStatus() != Status.WAITING; } } jboss-threads-2.3.2.Final/src/main/java/org/jboss/threads/AtomicArray.java000066400000000000000000000353161325274360100264040ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2017 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.threads; import java.lang.reflect.Array; import java.util.Arrays; import java.util.Comparator; import java.util.concurrent.atomic.AtomicReferenceFieldUpdater; import org.wildfly.common.Assert; /** * Utility for snapshot/copy-on-write arrays. To use these methods, two things are required: an immutable array * stored on a volatile field, and an instance of * {@link java.util.concurrent.atomic.AtomicReferenceFieldUpdater AtomicReferenceFieldUpdater} * which corresponds to that field. Some of these methods perform multi-step operations; if the array field value is * changed in the middle of such an operation, the operation is retried. To avoid spinning, in some situations it * may be advisable to hold a write lock to prevent multiple concurrent updates. * * @param the type which contains the target field * @param the array value type */ public final class AtomicArray { @SuppressWarnings("AtomicFieldUpdaterNotStaticFinal") private final AtomicReferenceFieldUpdater updater; private final V[] emptyArray; private AtomicArray(AtomicReferenceFieldUpdater updater, V[] emptyArray) { this.updater = updater; this.emptyArray = emptyArray; } /** * Construct a new instance. * * @param updater the field updater * @param componentType the component class * @param the type which contains the target field * @param the array value type * @return the new instance */ public static AtomicArray create(AtomicReferenceFieldUpdater updater, Class componentType) { Assert.checkNotNullParam("updater", updater); Assert.checkNotNullParam("componentType", componentType); return new AtomicArray<>(updater, (V[]) Array.newInstance(componentType, 0)); } /** * Construct a new instance. * * @param updater the field updater * @param creator the array creator * @param the type which contains the target field * @param the array value type * @return the new instance * @deprecated Use {@link #create(AtomicReferenceFieldUpdater, Object[])} or {@link #create(AtomicReferenceFieldUpdater, Class)} instead. */ @Deprecated public static AtomicArray create(AtomicReferenceFieldUpdater updater, Creator creator) { Assert.checkNotNullParam("updater", updater); Assert.checkNotNullParam("creator", creator); return new AtomicArray<>(updater, creator.create(0)); } /** * Construct a new instance. * * @param updater the field updater * @param emptyArray an empty array of the target type * @param the type which contains the target field * @param the array value type * @return the new instance */ public static AtomicArray create(AtomicReferenceFieldUpdater updater, V[] emptyArray) { Assert.checkNotNullParam("updater", updater); Assert.checkNotNullParam("emptyArray", emptyArray); if (emptyArray.length > 0) { throw Messages.msg.arrayNotEmpty(); } return new AtomicArray<>(updater, emptyArray); } /** * Convenience method to set the field value to the empty array. Empty array instances are shared. * * @param instance the instance holding the field */ public void clear(T instance) { updater.set(instance, emptyArray); } /** * Update the value of this array. * * @param instance the instance holding the field * @param value the new value */ public void set(T instance, V[] value) { updater.set(instance, value); } /** * Atomically get and update the value of this array. * * @param instance the instance holding the field * @param value the new value */ public V[] getAndSet(T instance, V[] value) { return updater.getAndSet(instance, value); } /** * Atomically replace the array with a new array which is one element longer, and which includes the given value. * * @param instance the instance holding the field * @param value the updated value */ public void add(T instance, V value) { final AtomicReferenceFieldUpdater updater = this.updater; for (;;) { final V[] oldVal = updater.get(instance); final int oldLen = oldVal.length; final V[] newVal = Arrays.copyOf(oldVal, oldLen + 1); newVal[oldLen] = value; if (updater.compareAndSet(instance, oldVal, newVal)) { return; } } } /** * Atomically replace the array with a new array which is one element longer, and which includes the given value, * if the value is not already present within the array. This method does a linear search for the target value. * * @param instance the instance holding the field * @param value the updated value * @param identity {@code true} if comparisons should be done using reference identity, or {@code false} to use the {@code equals()} method * @return {@code true} if the value was added, or {@code false} if it was already present */ public boolean addIfAbsent(T instance, V value, boolean identity) { final AtomicReferenceFieldUpdater updater = this.updater; for (;;) { final V[] oldVal = updater.get(instance); final int oldLen = oldVal.length; if (identity || value == null) { for (int i = 0; i < oldLen; i++) { if (oldVal[i] == value) { return false; } } } else { for (int i = 0; i < oldLen; i++) { if (value.equals(oldVal[i])) { return false; } } } final V[] newVal = Arrays.copyOf(oldVal, oldLen + 1); newVal[oldLen] = value; if (updater.compareAndSet(instance, oldVal, newVal)) { return true; } } } /** * Atomically replace the array with a new array which does not include the first occurrance of the given value, if * the value is present in the array. * * @param instance the instance holding the field * @param value the updated value * @param identity {@code true} if comparisons should be done using reference identity, or {@code false} to use the {@code equals()} method * @return {@code true} if the value was removed, or {@code false} if it was not present */ public boolean remove(T instance, V value, boolean identity) { final AtomicReferenceFieldUpdater updater = this.updater; for (;;) { final V[] oldVal = updater.get(instance); final int oldLen = oldVal.length; if (oldLen == 0) { return false; } else { int index = -1; if (identity || value == null) { for (int i = 0; i < oldLen; i++) { if (oldVal[i] == value) { index = i; break; } } } else { for (int i = 0; i < oldLen; i++) { if (value.equals(oldVal[i])) { index = i; break; } } } if (index == -1) { return false; } final V[] newVal = Arrays.copyOf(oldVal, oldLen - 1); System.arraycopy(oldVal, index + 1, newVal, index, oldLen - index - 1); if (updater.compareAndSet(instance, oldVal, newVal)) { return true; } } } } /** * Atomically replace the array with a new array which does not include any occurrances of the given value, if * the value is present in the array. * * @param instance the instance holding the field * @param value the updated value * @param identity {@code true} if comparisons should be done using reference identity, or {@code false} to use the {@code equals()} method * @return the number of values removed */ public int removeAll(T instance, V value, boolean identity) { final AtomicReferenceFieldUpdater updater = this.updater; for (;;) { final V[] oldVal = updater.get(instance); final int oldLen = oldVal.length; if (oldLen == 0) { return 0; } else { final boolean[] removeSlots = new boolean[oldLen]; int removeCount = 0; if (identity || value == null) { for (int i = 0; i < oldLen; i++) { if (oldVal[i] == value) { removeSlots[i] = true; removeCount++; } } } else { for (int i = 0; i < oldLen; i++) { if (value.equals(oldVal[i])) { removeSlots[i] = true; removeCount++; } } } if (removeCount == 0) { return 0; } final int newLen = oldLen - removeCount; final V[] newVal; if (newLen == 0) { newVal = emptyArray; } else { newVal = Arrays.copyOf(emptyArray, newLen); for (int i = 0, j = 0; i < oldLen; i ++) { if (! removeSlots[i]) { newVal[j++] = oldVal[i]; } } } if (updater.compareAndSet(instance, oldVal, newVal)) { return removeCount; } } } } /** * Add a value to a sorted array. Does not check for duplicates. * * @param instance the instance holding the field * @param value the value to add * @param comparator a comparator, or {@code null} to use natural ordering */ public void add(T instance, V value, Comparator comparator) { final AtomicReferenceFieldUpdater updater = this.updater; for (;;) { final V[] oldVal = updater.get(instance); final int oldLen = oldVal.length; final int pos = insertionPoint(Arrays.binarySearch(oldVal, value, comparator)); final V[] newVal = Arrays.copyOf(oldVal, oldLen + 1); newVal[pos] = value; System.arraycopy(oldVal, pos, newVal, pos + 1, oldLen - pos); if (updater.compareAndSet(instance, oldVal, newVal)) { return; } } } /** * Add a value to a sorted array if it is not already present. Does not check for duplicates. * * @param instance the instance holding the field * @param value the value to add * @param comparator a comparator, or {@code null} to use natural ordering */ public boolean addIfAbsent(T instance, V value, Comparator comparator) { final AtomicReferenceFieldUpdater updater = this.updater; for (;;) { final V[] oldVal = updater.get(instance); final int oldLen = oldVal.length; final int pos = Arrays.binarySearch(oldVal, value, comparator); if (pos < 0) { return false; } final V[] newVal = Arrays.copyOf(oldVal, oldLen + 1); newVal[pos] = value; System.arraycopy(oldVal, pos, newVal, pos + 1, oldLen - pos); if (updater.compareAndSet(instance, oldVal, newVal)) { return true; } } } /** * Remove a value to a sorted array. Does not check for duplicates. If there are multiple occurrances of a value, * there is no guarantee as to which one is removed. * * @param instance the instance holding the field * @param value the value to remove * @param comparator a comparator, or {@code null} to use natural ordering */ public boolean remove(T instance, V value, Comparator comparator) { final AtomicReferenceFieldUpdater updater = this.updater; for (;;) { final V[] oldVal = updater.get(instance); final int oldLen = oldVal.length; if (oldLen == 0) { return false; } else { final int pos = Arrays.binarySearch(oldVal, value, comparator); if (pos < 0) { return false; } final V[] newVal = Arrays.copyOf(oldVal, oldLen - 1); System.arraycopy(oldVal, pos + 1, newVal, pos, oldLen - pos - 1); if (updater.compareAndSet(instance, oldVal, newVal)) { return true; } } } } /** * Sort an array. * * @param instance the instance holding the field * @param comparator a comparator, or {@code null} to use natural ordering */ public void sort(T instance, Comparator comparator) { final AtomicReferenceFieldUpdater updater = this.updater; for (;;) { final V[] oldVal = updater.get(instance); if (oldVal.length == 0) { return; } final V[] newVal = oldVal.clone(); Arrays.sort(newVal, comparator); if (updater.compareAndSet(instance, oldVal, newVal)) { return; } } } private static int insertionPoint(int searchResult) { return searchResult > 0 ? searchResult : - (searchResult + 1); } @Deprecated public interface Creator { V[] create(int len); } } jboss-threads-2.3.2.Final/src/main/java/org/jboss/threads/BalancingExecutor.java000066400000000000000000000067141325274360100275660ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2017 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.threads; import static java.util.concurrent.atomic.AtomicReferenceFieldUpdater.newUpdater; import java.util.concurrent.Executor; import java.util.concurrent.RejectedExecutionException; import java.util.concurrent.ThreadLocalRandom; import org.wildfly.common.Assert; /** * A simple load-balancing executor. If no delegate executors are defined, then tasks are rejected. Executors are * chosen in a random fashion. */ public class BalancingExecutor implements Executor { private static final Executor[] NO_EXECUTORS = new Executor[0]; private volatile Executor[] executors = NO_EXECUTORS; private static final AtomicArray executorsUpdater = AtomicArray.create(newUpdater(BalancingExecutor.class, Executor[].class, "executors"), NO_EXECUTORS); /** * Construct a new instance. */ public BalancingExecutor() { } /** * Construct a new instance. * * @param executors the initial list of executors to delegate to */ public BalancingExecutor(Executor... executors) { if (executors != null && executors.length > 0) { final Executor[] clone = executors.clone(); for (int i = 0; i < clone.length; i++) { Assert.checkNotNullArrayParam("executors", i, clone[i]); } executorsUpdater.set(this, clone); } else { executorsUpdater.clear(this); } } /** * Execute a task. * * @param command the task to execute * @throws RejectedExecutionException if no executors are available to run the task */ public void execute(final Runnable command) throws RejectedExecutionException { final Executor[] executors = this.executors; final int len = executors.length; if (len == 0) { throw Messages.msg.noExecutorsAvailable(); } executors[ThreadLocalRandom.current().nextInt(len)].execute(command); } /** * Clear out all delegate executors at once. Tasks will be rejected until another delegate executor is added. */ public void clear() { executorsUpdater.clear(this); } /** * Add a delegate executor. * * @param executor the executor to add */ public void addExecutor(final Executor executor) { Assert.checkNotNullParam("executor", executor); synchronized (this) { executorsUpdater.add(this, executor); } } /** * Remove a delegate executor. * * @param executor the executor to remove */ public void removeExecutor(final Executor executor) { if (executor == null) { return; } synchronized (this) { executorsUpdater.remove(this, executor, true); } } } jboss-threads-2.3.2.Final/src/main/java/org/jboss/threads/BlockingExecutor.java000066400000000000000000000123231325274360100274310ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2017 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.threads; import java.util.concurrent.Executor; import java.util.concurrent.RejectedExecutionException; import java.util.concurrent.TimeUnit; import org.wildfly.common.Assert; /** * An executor which can optionally block or not block on task submission. * * @deprecated Executors in this package will always accept tasks immediately. */ @Deprecated public interface BlockingExecutor extends Executor { /** * Executes the given command at some time in the future. The command may execute in a new thread, in a pooled thread, * or in the calling thread, at the discretion of the Executor implementation. The call may block * or not block, depending on the configuration of the executor. * * @param task the task to submit * * @throws ExecutionInterruptedException if the executor is configured to block, and the thread was interrupted while waiting * for the task to be accepted * @throws StoppedExecutorException if the executor was shut down before the task was accepted * @throws ThreadCreationException if a thread could not be created for some reason * @throws RejectedExecutionException if execution is rejected for some other reason * @throws NullPointerException if command is {@code null} */ void execute(Runnable task); /** * Execute a task, blocking until it can be accepted, or until the calling thread is interrupted. * * @param task the task to submit * @throws StoppedExecutorException if the executor was shut down before the task was accepted * @throws ThreadCreationException if a thread could not be created for some reason * @throws RejectedExecutionException if execution is rejected for some other reason * @throws InterruptedException if the current thread was interrupted before the task could be accepted * @throws NullPointerException if command is {@code null} */ void executeBlocking(Runnable task) throws RejectedExecutionException, InterruptedException; /** * Execute a task, blocking until it can be accepted, a timeout elapses, or the calling thread is interrupted. * * @param task the task to submit * @param timeout the amount of time to wait * @param unit the unit of time * @throws ExecutionTimedOutException if the timeout elapsed before a task could be accepted * @throws StoppedExecutorException if the executor was shut down before the task was accepted * @throws ThreadCreationException if a thread could not be created for some reason * @throws RejectedExecutionException if execution is rejected for some other reason * @throws InterruptedException if the current thread was interrupted before the task could be accepted * @throws NullPointerException if command is {@code null} */ void executeBlocking(Runnable task, long timeout, TimeUnit unit) throws RejectedExecutionException, InterruptedException; /** * Execute a task, without blocking. * * @param task the task to submit * @throws StoppedExecutorException if the executor was shut down before the task was accepted * @throws ThreadCreationException if a thread could not be created for some reason * @throws RejectedExecutionException if execution is rejected for some other reason * @throws NullPointerException if command is {@code null} */ void executeNonBlocking(Runnable task) throws RejectedExecutionException; /** * Convert an executor to a "blocking" executor which never actually blocks. * * @param executor the executor (must not be {@code null}) * @return the blocking executor (not {@code null}) */ static BlockingExecutor of(Executor executor) { Assert.checkNotNullParam("executor", executor); return executor instanceof BlockingExecutor ? (BlockingExecutor) executor : new BlockingExecutor() { public void execute(final Runnable task) { executor.execute(task); } public void executeBlocking(final Runnable task) throws RejectedExecutionException, InterruptedException { executor.execute(task); } public void executeBlocking(final Runnable task, final long timeout, final TimeUnit unit) throws RejectedExecutionException, InterruptedException { executor.execute(task); } public void executeNonBlocking(final Runnable task) throws RejectedExecutionException { executor.execute(task); } }; } } jboss-threads-2.3.2.Final/src/main/java/org/jboss/threads/BlockingExecutorService.java000066400000000000000000000017421325274360100307550ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2017 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.threads; import java.util.concurrent.ExecutorService; /** * A blocking executor service. * * @author David M. Lloyd */ @Deprecated public interface BlockingExecutorService extends BlockingExecutor, ExecutorService { } jboss-threads-2.3.2.Final/src/main/java/org/jboss/threads/CleanupExecutor.java000066400000000000000000000027001325274360100272660ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2017 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.threads; class CleanupExecutor implements DirectExecutor { private final Runnable cleaner; private final DirectExecutor delegate; private static final DirectExecutor CLEANER_EXECUTOR = JBossExecutors.exceptionLoggingExecutor(JBossExecutors.directExecutor()); CleanupExecutor(final Runnable cleaner, final DirectExecutor delegate) { this.cleaner = cleaner; this.delegate = delegate; } public void execute(final Runnable command) { try { delegate.execute(command); } finally { CLEANER_EXECUTOR.execute(cleaner); } } public String toString() { return String.format("%s (cleanup task=%s) -> %s", super.toString(), cleaner, delegate); } }jboss-threads-2.3.2.Final/src/main/java/org/jboss/threads/CompositeTask.java000066400000000000000000000022251325274360100267470ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2017 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.threads; final class CompositeTask implements Runnable { private final Runnable[] runnables; CompositeTask(final Runnable[] runnables) { this.runnables = runnables; } public void run() { for (Runnable runnable : runnables) { runnable.run(); } } public String toString() { return String.format("%s (%d task(s))", super.toString(), Integer.valueOf(runnables.length)); } } jboss-threads-2.3.2.Final/src/main/java/org/jboss/threads/ContextClassLoaderExecutor.java000066400000000000000000000030321325274360100314370ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2017 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ 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); } } jboss-threads-2.3.2.Final/src/main/java/org/jboss/threads/ContextClassLoaderSavingRunnable.java000066400000000000000000000025311325274360100325620ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2017 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.threads; class ContextClassLoaderSavingRunnable implements Runnable { private final ClassLoader loader; private final Runnable delegate; ContextClassLoaderSavingRunnable(final ClassLoader loader, final Runnable delegate) { this.loader = loader; this.delegate = delegate; } public void run() { final Thread currentThread = Thread.currentThread(); final ClassLoader old = JBossExecutors.getAndSetContextClassLoader(currentThread, loader); try { delegate.run(); } finally { JBossExecutors.setContextClassLoader(currentThread, old); } } } jboss-threads-2.3.2.Final/src/main/java/org/jboss/threads/DeclaredFieldAction.java000066400000000000000000000023761325274360100277760ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2018 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.threads; import java.lang.reflect.Field; import java.security.PrivilegedAction; /** */ final class DeclaredFieldAction implements PrivilegedAction { private final Class clazz; private final String fieldName; DeclaredFieldAction(final Class clazz, final String fieldName) { this.clazz = clazz; this.fieldName = fieldName; } public Field run() { try { return clazz.getDeclaredField(fieldName); } catch (NoSuchFieldException e) { return null; } } } jboss-threads-2.3.2.Final/src/main/java/org/jboss/threads/DelegatingBlockingExecutor.java000066400000000000000000000037111325274360100314160ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2017 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.threads; import java.util.concurrent.RejectedExecutionException; import java.util.concurrent.TimeUnit; /** * An executor that simply delegates to another executor. Use instances of this class to hide extra methods on * another executor. */ @Deprecated class DelegatingBlockingExecutor implements BlockingExecutor { private final BlockingExecutor delegate; DelegatingBlockingExecutor(final BlockingExecutor delegate) { this.delegate = delegate; } protected BlockingExecutor getDelegate() { return delegate; } public void execute(final Runnable command) { delegate.execute(command); } public void executeBlocking(final Runnable task) throws RejectedExecutionException, InterruptedException { delegate.executeBlocking(task); } public void executeBlocking(final Runnable task, final long timeout, final TimeUnit unit) throws RejectedExecutionException, InterruptedException { delegate.executeBlocking(task, timeout, unit); } public void executeNonBlocking(final Runnable task) throws RejectedExecutionException { delegate.executeNonBlocking(task); } public String toString() { return String.format("%s -> %s", super.toString(), delegate); } }jboss-threads-2.3.2.Final/src/main/java/org/jboss/threads/DelegatingBlockingExecutorService.java000066400000000000000000000054361325274360100327450ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2017 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.threads; import java.util.List; import java.util.concurrent.AbstractExecutorService; import java.util.concurrent.ExecutorService; import java.util.concurrent.RejectedExecutionException; import java.util.concurrent.TimeUnit; /** * @author David M. Lloyd */ @Deprecated class DelegatingBlockingExecutorService extends AbstractExecutorService implements BlockingExecutorService { private final BlockingExecutor delegate; DelegatingBlockingExecutorService(final BlockingExecutor delegate) { this.delegate = delegate; } public void execute(final Runnable command) { delegate.execute(command); } public boolean isShutdown() { // container managed executors are never shut down from the application's perspective return false; } public boolean isTerminated() { // container managed executors are never shut down from the application's perspective return false; } public boolean awaitTermination(final long timeout, final TimeUnit unit) throws InterruptedException { return false; } public void shutdown() { throw Messages.msg.notAllowedContainerManaged("shutdown"); } public List shutdownNow() { throw Messages.msg.notAllowedContainerManaged("shutdownNow"); } public void executeBlocking(final Runnable task) throws RejectedExecutionException, InterruptedException { delegate.executeBlocking(task); } public void executeBlocking(final Runnable task, final long timeout, final TimeUnit unit) throws RejectedExecutionException, InterruptedException { delegate.executeBlocking(task, timeout, unit); } public void executeNonBlocking(final Runnable task) throws RejectedExecutionException { delegate.executeNonBlocking(task); } public static ExecutorService directExecutorService() { return new DelegatingExecutorService(JBossExecutors.directExecutor()); } public String toString() { return String.format("%s -> %s", super.toString(), delegate); } } jboss-threads-2.3.2.Final/src/main/java/org/jboss/threads/DelegatingDirectBlockingExecutor.java000066400000000000000000000040661325274360100325550ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2017 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.threads; import java.util.concurrent.RejectedExecutionException; import java.util.concurrent.TimeUnit; @Deprecated class DelegatingDirectBlockingExecutor implements BlockingExecutor, DirectExecutor { private final DirectExecutor delegate; DelegatingDirectBlockingExecutor(final DirectExecutor delegate) { this.delegate = delegate; } public void execute(final Runnable task) { delegate.execute(task); } public void executeNonBlocking(final Runnable task) throws RejectedExecutionException { delegate.execute(task); } public void executeBlocking(final Runnable task, final long timeout, final TimeUnit unit) throws RejectedExecutionException, InterruptedException { try { delegate.execute(task); } catch (ExecutionInterruptedException e) { if (Thread.interrupted()) { throw new InterruptedException(); } else { throw e; } } } public void executeBlocking(final Runnable task) throws RejectedExecutionException, InterruptedException { try { delegate.execute(task); } catch (ExecutionInterruptedException e) { if (Thread.interrupted()) { throw new InterruptedException(); } else { throw e; } } } } jboss-threads-2.3.2.Final/src/main/java/org/jboss/threads/DelegatingDirectExecutor.java000066400000000000000000000022311325274360100310740ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2017 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.threads; /** * A direct executor that simply delegates to another direct executor. Use instances of this class to hide extra methods on * another executor. */ class DelegatingDirectExecutor extends DelegatingExecutor implements DirectExecutor { DelegatingDirectExecutor(final DirectExecutor delegate) { super(delegate); } protected DirectExecutor getDelegate() { return (DirectExecutor) super.getDelegate(); } } jboss-threads-2.3.2.Final/src/main/java/org/jboss/threads/DelegatingDirectExecutorService.java000066400000000000000000000020021325274360100324110ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2017 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.threads; /** * A {@code DirectExecutor} version of {@code ProtectedExecutorService}. */ class DelegatingDirectExecutorService extends DelegatingExecutorService implements DirectExecutorService { DelegatingDirectExecutorService(final DirectExecutor delegate) { super(delegate); } } jboss-threads-2.3.2.Final/src/main/java/org/jboss/threads/DelegatingExecutor.java000066400000000000000000000027101325274360100277430ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2017 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.threads; import java.util.concurrent.Executor; /** * An executor that simply delegates to another executor. Use instances of this class to hide extra methods on * another executor. */ class DelegatingExecutor implements Executor { private final Executor delegate; DelegatingExecutor(final Executor delegate) { this.delegate = delegate; } protected Executor getDelegate() { return delegate; } /** * Execute a task by passing it to the delegate executor. * * @param command the task */ public void execute(final Runnable command) { delegate.execute(command); } public String toString() { return String.format("%s -> %s", super.toString(), delegate); } } jboss-threads-2.3.2.Final/src/main/java/org/jboss/threads/DelegatingExecutorService.java000066400000000000000000000044041325274360100312660ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2017 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.threads; import java.util.concurrent.ExecutorService; import java.util.concurrent.TimeUnit; import java.util.concurrent.AbstractExecutorService; import java.util.concurrent.Executor; import java.util.List; /** * An implementation of {@code ExecutorService} that delegates to the real executor, while disallowing termination. */ class DelegatingExecutorService extends AbstractExecutorService implements ExecutorService { private final Executor delegate; DelegatingExecutorService(final Executor delegate) { this.delegate = delegate; } public void execute(final Runnable command) { delegate.execute(command); } public boolean isShutdown() { // container managed executors are never shut down from the application's perspective return false; } public boolean isTerminated() { // container managed executors are never shut down from the application's perspective return false; } public boolean awaitTermination(final long timeout, final TimeUnit unit) throws InterruptedException { return false; } public void shutdown() { throw Messages.msg.notAllowedContainerManaged("shutdown"); } public List shutdownNow() { throw Messages.msg.notAllowedContainerManaged("shutdownNow"); } public static ExecutorService directExecutorService() { return new DelegatingExecutorService(JBossExecutors.directExecutor()); } public String toString() { return String.format("%s -> %s", super.toString(), delegate); } } jboss-threads-2.3.2.Final/src/main/java/org/jboss/threads/DelegatingRunnable.java000066400000000000000000000021731325274360100277160ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2017 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.threads; class DelegatingRunnable implements Runnable { private final Runnable delegate; DelegatingRunnable(final Runnable delegate) { this.delegate = delegate; } protected Runnable getDelegate() { return delegate; } public void run() { delegate.run(); } public String toString() { return String.format("%s -> %s", super.toString(), delegate); } } jboss-threads-2.3.2.Final/src/main/java/org/jboss/threads/DelegatingScheduledExecutorService.java000066400000000000000000000041671325274360100331150ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2017 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.threads; import java.util.concurrent.TimeUnit; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ScheduledFuture; import java.util.concurrent.Callable; /** * An implementation of {@code ScheduledExecutorService} that delegates to the real executor, while disallowing termination. */ class DelegatingScheduledExecutorService extends DelegatingExecutorService implements ScheduledExecutorService { private final ScheduledExecutorService delegate; DelegatingScheduledExecutorService(final ScheduledExecutorService delegate) { super(delegate); this.delegate = delegate; } public ScheduledFuture schedule(final Runnable command, final long delay, final TimeUnit unit) { return delegate.schedule(command, delay, unit); } public ScheduledFuture schedule(final Callable callable, final long delay, final TimeUnit unit) { return delegate.schedule(callable, delay, unit); } public ScheduledFuture scheduleAtFixedRate(final Runnable command, final long initialDelay, final long period, final TimeUnit unit) { return delegate.scheduleAtFixedRate(command, initialDelay, period, unit); } public ScheduledFuture scheduleWithFixedDelay(final Runnable command, final long initialDelay, final long delay, final TimeUnit unit) { return delegate.scheduleWithFixedDelay(command, initialDelay, delay, unit); } }jboss-threads-2.3.2.Final/src/main/java/org/jboss/threads/DelegatingWrappedExecutor.java000066400000000000000000000022701325274360100312670ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2017 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.threads; import java.util.concurrent.Executor; class DelegatingWrappedExecutor implements Executor { private final WrappingExecutor delegate; private final DirectExecutor taskWrapper; DelegatingWrappedExecutor(final WrappingExecutor delegate, final DirectExecutor taskWrapper) { this.delegate = delegate; this.taskWrapper = taskWrapper; } public void execute(final Runnable command) { delegate.execute(taskWrapper, command); } } jboss-threads-2.3.2.Final/src/main/java/org/jboss/threads/DelegatingWrappingExecutor.java000066400000000000000000000022661325274360100314610ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2017 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.threads; import java.util.concurrent.Executor; import java.util.concurrent.RejectedExecutionException; class DelegatingWrappingExecutor extends DelegatingExecutor implements WrappingExecutor { DelegatingWrappingExecutor(final Executor delegate) { super(delegate); } public void execute(final DirectExecutor directExecutor, final Runnable task) throws RejectedExecutionException { execute(JBossExecutors.executorTask(directExecutor, task)); } } jboss-threads-2.3.2.Final/src/main/java/org/jboss/threads/Dependency.java000066400000000000000000000135601325274360100262440ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2017 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.threads; import java.util.ArrayList; import java.util.List; import java.util.concurrent.atomic.AtomicIntegerFieldUpdater; import java.util.concurrent.Executor; import java.util.concurrent.RejectedExecutionException; import org.wildfly.common.Assert; /** * A task which depends on other tasks, and which may have tasks depending upon it. Such a task is automatically * run when using a provided executor when all its dependencies are satisfied. */ public final class Dependency { private static final AtomicIntegerFieldUpdater depUpdater = AtomicIntegerFieldUpdater.newUpdater(Dependency.class, "remainingDependencies"); /** * Number of dependencies left before this task can start. */ @SuppressWarnings({ "UnusedDeclaration" }) private volatile int remainingDependencies; private final Executor executor; private final Object lock = new Object(); private Runner runner; private State state; Dependency(final Executor executor, final Runnable runnable, final int initialDepCount) { this.executor = executor; synchronized (lock) { runner = new Runner(runnable); state = State.WAITING; remainingDependencies = initialDepCount; } } void addDependent(Dependency task) { synchronized (lock) { switch (state) { case WAITING: case RUNNING: runner.dependents.add(task); return; case FAILED: return; case DONE: break; // fall out of lock default: throw Assert.impossibleSwitchCase(state); } } task.dependencyFinished(); } void dependencyFinished() { final AtomicIntegerFieldUpdater updater = depUpdater; final int res = updater.decrementAndGet(this); if (res == 0) { final Dependency.Runner runner = this.runner; synchronized (lock) { try { executor.execute(runner); state = State.RUNNING; } catch (RejectedExecutionException e) { Messages.msg.taskSubmitFailed(e, runner.runnable); state = State.FAILED; // clear stuff out since this object will likely be kept alive longer than these objects need to be runner.runnable = null; runner.dependents = null; this.runner = null; } } } else if (res < 0) { // oops? updater.incrementAndGet(this); } } private void dependencyFailed() { final AtomicIntegerFieldUpdater updater = depUpdater; final int res = updater.decrementAndGet(this); synchronized (lock) { state = State.FAILED; final Dependency.Runner runner = this.runner; // clear stuff out since this object will likely be kept alive longer than these objects need to be runner.runnable = null; runner.dependents = null; this.runner = null; } if (res < 0) { // oops? updater.incrementAndGet(this); } } private class Runner implements Runnable { private List dependents = new ArrayList(); private Runnable runnable; public Runner(final Runnable runnable) { this.runnable = runnable; } public void run() { boolean ok = false; CTH.set(Dependency.this); try { runnable.run(); ok = true; } finally { CTH.set(null); final List tasks; synchronized (lock) { tasks = dependents; // clear stuff out in case some stupid executor holds on to the runnable dependents = null; runnable = null; runner = null; state = ok ? State.DONE : State.FAILED; } if (ok) { for (Dependency task : tasks) { task.dependencyFinished(); } } else { for (Dependency task : tasks) { task.dependencyFailed(); } } } } } private enum State { /** * Waiting for dependencies to be resolved. */ WAITING, /** * Now running. */ RUNNING, /** * Execution failed. */ FAILED, /** * Execution completed. */ DONE, } /** * Get the dependency task which this thread is currently running. This may be used to add dependencies on the currently * running task. * * @return the currently running task, or {@code null} if the current thread is not running a dependency task */ public static Dependency currentTask() { return CTH.get(); } private static final ThreadLocal CTH = new ThreadLocal(); } jboss-threads-2.3.2.Final/src/main/java/org/jboss/threads/DependencyTaskBuilder.java000066400000000000000000000051711325274360100303750ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2017 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.threads; import java.util.Collection; import java.util.LinkedHashSet; import java.util.Arrays; import java.util.concurrent.Executor; import org.wildfly.common.Assert; /** * A builder for a dependency task. */ public final class DependencyTaskBuilder { private final Collection dependencies = new LinkedHashSet(); private final Executor executor; private final Runnable task; DependencyTaskBuilder(final Executor executor, final Runnable task) { this.executor = executor; this.task = task; } /** * Add a dependency. * * @param dependency the dependency * @return this builder */ public DependencyTaskBuilder add(Dependency dependency) { Assert.checkNotNullParam("dependency", dependency); dependencies.add(dependency); return this; } /** * Add many dependencies. * * @param dependencies the dependencies * @return this builder */ public DependencyTaskBuilder add(Collection dependencies) { this.dependencies.addAll(dependencies); return this; } /** * Add many dependencies. * * @param dependencies the dependencies * @return this builder */ public DependencyTaskBuilder add(Dependency... dependencies) { this.dependencies.addAll(Arrays.asList(dependencies)); return this; } /** * Create, and possibly execute, a dependent task from this builder. * * @return the new dependent task */ public Dependency create() { final Collection dependencies = this.dependencies; final Dependency dependentTask = new Dependency(executor, task, dependencies.size() + 1); for (Dependency dependency : dependencies) { dependency.addDependent(dependentTask); } dependentTask.dependencyFinished(); return dependentTask; } } jboss-threads-2.3.2.Final/src/main/java/org/jboss/threads/DirectExecutor.java000066400000000000000000000041651325274360100271200ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2017 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.threads; import java.util.concurrent.Executor; /** * A direct executor. Such an executor is required to run the given task in the current thread rather than * delegate to a thread pool; furthermore, the task is guaranteed to be terminated when the call to the * {@link #execute(Runnable)} method returns. * * @see JBossExecutors#directExecutor() * @see JBossExecutors#rejectingExecutor() * @see JBossExecutors#discardingExecutor() * @see JBossExecutors#privilegedExecutor(org.jboss.threads.DirectExecutor) * @see JBossExecutors#contextClassLoaderExecutor(org.jboss.threads.DirectExecutor, java.lang.ClassLoader) * @see JBossExecutors#threadNameExecutor(org.jboss.threads.DirectExecutor, java.lang.String) * @see JBossExecutors#threadNameNotateExecutor(org.jboss.threads.DirectExecutor, java.lang.String) * @see JBossExecutors#exceptionLoggingExecutor(DirectExecutor, org.jboss.logging.Logger) * @see JBossExecutors#exceptionLoggingExecutor(DirectExecutor) * @see JBossExecutors#resettingExecutor(org.jboss.threads.DirectExecutor) */ public interface DirectExecutor extends Executor { /** * Executes the given command in the calling thread. * * @param command the runnable task * * @throws java.util.concurrent.RejectedExecutionException if this task cannot be accepted for execution * @throws NullPointerException if command is null */ void execute(Runnable command); } jboss-threads-2.3.2.Final/src/main/java/org/jboss/threads/DirectExecutorService.java000066400000000000000000000020031325274360100304260ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2017 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.threads; import java.util.concurrent.ExecutorService; /** * A direct executor service. Such an executor service is required to run the given task in the current thread rather than * delegate to a thread pool. */ public interface DirectExecutorService extends DirectExecutor, ExecutorService { } jboss-threads-2.3.2.Final/src/main/java/org/jboss/threads/DiscardingExecutor.java000066400000000000000000000020421325274360100277450ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2017 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.threads; class DiscardingExecutor implements DirectExecutor { static final DiscardingExecutor INSTANCE = new DiscardingExecutor(); private DiscardingExecutor() { } public void execute(final Runnable command) { // nothing } public String toString() { return "Discarding executor"; } } jboss-threads-2.3.2.Final/src/main/java/org/jboss/threads/EnhancedQueueExecutor.java000066400000000000000000002643221325274360100304230ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2017 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.threads; import static java.lang.Math.max; import static java.lang.Thread.holdsLock; import static java.security.AccessController.doPrivileged; import static java.security.AccessController.getContext; import static java.util.concurrent.locks.LockSupport.*; import java.lang.management.ManagementFactory; import java.security.AccessControlContext; import java.security.PrivilegedAction; import java.util.ArrayList; import java.util.Collections; import java.util.Hashtable; import java.util.List; import java.util.Set; import java.util.concurrent.AbstractExecutorService; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.Executor; import java.util.concurrent.Executors; import java.util.concurrent.RejectedExecutionException; import java.util.concurrent.ThreadFactory; import java.util.concurrent.ThreadLocalRandom; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicIntegerFieldUpdater; import java.util.concurrent.atomic.AtomicLongFieldUpdater; import java.util.concurrent.atomic.AtomicReferenceFieldUpdater; import java.util.concurrent.atomic.LongAdder; import javax.management.ObjectInstance; import javax.management.ObjectName; import org.jboss.threads.management.ManageableThreadPoolExecutorService; import org.jboss.threads.management.StandardThreadPoolMXBean; import org.wildfly.common.Assert; import org.wildfly.common.annotation.NotNull; import sun.misc.Contended; /** * A task-or-thread queue backed thread pool executor service. Tasks are added in a FIFO manner, and consumers in a LIFO manner. * Threads are only ever created in the event that there are no idle threads available to service a task, which, when * combined with the LIFO-based consumer behavior, means that the thread pool will generally trend towards the minimum * necessary size. In addition, the optional {@linkplain #setGrowthResistance(float) growth resistance feature} can * be used to further govern the thread pool size. *

* New instances of this thread pool are created by constructing and configuring a {@link Builder} instance, and calling * its {@link Builder#build() build()} method. * * @author David M. Lloyd */ @Contended public final class EnhancedQueueExecutor extends AbstractExecutorService implements ManageableThreadPoolExecutorService { static { Version.getVersionString(); } /* ┌──────────────────────────┐ │ Explanation of operation │ └──────────────────────────┘ The primary mechanism of this executor is the special linked list/stack. This list has the following properties: • Multiple node types: ◦ Task nodes (TaskNode), which have the following properties: ▪ Strongly connected (no task is ever removed from the middle of the list; tail can always be found by following .next pointers) ▪ FIFO (insertion at tail.next, "removal" at head.next) ▪ Head and tail always refer to TaskNodes; head.next/tail.next are the "true" action points for all node types ▪ At least one dead task node is always in the list, thus the task is cleared after execution to avoid leaks ◦ Waiting consumer thread nodes (PoolThreadNode), which have the following properties: ▪ LIFO/FILO (insertion and removal at tail.next) ▪ Carrier for task handoff between producer and waiting consumer ◦ Waiting termination (awaitTermination) thread nodes (TerminateWaiterNode), which have the following properties: ▪ Append-only (insertion at tail.next.next...next) ▪ All removed at once when termination is complete ▪ If a thread stops waiting, the node remains (but its thread field is cleared to prevent (best-effort) useless unparks) ▪ Once cleared, the thread field can never be reinitialized • Concurrently accessed (multiple threads may read the list and update the head and tail pointers) • TaskNode.next may be any node type or null • PoolThreadNode.next may only be another PoolThreadNode or null • TerminateWaiterNode.next may only be another TerminateWaiterNode or null The secondary mechanism is the thread status atomic variable. It is logically a structure with the following fields: • Current thread count (currentSizeOf(), withCurrentSize()) • Core pool size (coreSizeOf(), withCoreSize()) • Max pool size (maxSizeOf(), withMaxSize()) • Shutdown-requested flag (isShutdownRequested(), withShutdownRequested()) • Shutdown-with-interrupt requested flag (isShutdownInterrupt(), withShutdownInterrupt()) • Shutdown-completed flag (isShutdownComplete(), withShutdownComplete()) • The decision to create a new thread is affected by whether the number of active threads is less than the core size; if not, then the growth resistance factor is applied to decide whether the task should be enqueued or a new thread begun. Note: the default growth resistance factor is 0% resistance. The final mechanism is the queue status atomic variable. It is logically a structure with the following fields: • Current queue size (currentQueueSizeOf(), withCurrentQueueSize()) • Queue size limit (maxQueueSizeOf(), withMaxQueueSize()) */ // ======================================================= // Optimization control flags // ======================================================= /** * A global hint which establishes whether it is recommended to disable uses of {@code EnhancedQueueExecutor}. * This hint defaults to {@code false} but can be changed to {@code true} by setting the {@code jboss.threads.eqe.disable} * property to {@code true} before this class is initialized. */ public static final boolean DISABLE_HINT = readBooleanProperty("disable", false); /** * Update the tail pointer opportunistically. */ static final boolean UPDATE_TAIL = readBooleanProperty("update-tail", false); /** * Update the summary statistics. */ static final boolean UPDATE_STATISTICS = readBooleanProperty("statistics", true); /** * Suppress queue limit and size tracking for performance. */ static final boolean NO_QUEUE_LIMIT = readBooleanProperty("unlimited-queue", false); /** * Establish a combined head/tail lock. */ static final boolean COMBINED_LOCK = readBooleanProperty("combined-lock", false); /** * Attempt to lock frequently-contended operations on the list tail. This defaults to {@code true} because * moderate contention among 8 CPUs can result in thousands of spin misses per execution. */ static final boolean TAIL_LOCK = COMBINED_LOCK || readBooleanProperty("tail-lock", true); /** * Attempt to lock frequently-contended operations on the list head. */ static final boolean HEAD_LOCK = COMBINED_LOCK || readBooleanProperty("head-lock", true); /** * Set the default value for whether an mbean is to be auto-registered for the thread pool. */ static final boolean REGISTER_MBEAN = readBooleanProperty("register-mbean", true); // ======================================================= // Constants // ======================================================= static final Executor DEFAULT_HANDLER = JBossExecutors.rejectingExecutor(); // ======================================================= // Locks // ======================================================= /** * The tail lock. Only used if {@link #TAIL_LOCK} is {@code true}. */ final Object tailLock = new Object(); /** * The head lock. Only used if {@link #HEAD_LOCK} is {@code true}. */ final Object headLock = COMBINED_LOCK ? tailLock : new Object(); // ======================================================= // Immutable configuration fields // ======================================================= /** * The thread factory. */ private final ThreadFactory threadFactory; /** * The approximate set of pooled threads. */ private final Set runningThreads = Collections.newSetFromMap(new ConcurrentHashMap<>()); /** * The management bean instance. */ private final MXBeanImpl mxBean; /** * The MBean registration handle (if any). */ private final ObjectInstance handle; /** * The access control context of the creating thread. */ private final AccessControlContext acc; // ======================================================= // Current state fields // ======================================================= /** * The node preceding the head node; this field is not {@code null}. This is * the removal point for tasks (and the insertion point for waiting threads). */ @NotNull @SuppressWarnings("unused") // used by field updater volatile TaskNode head; /** * The node preceding the tail node; this field is not {@code null}. This * is the insertion point for tasks (and the removal point for waiting threads). */ @NotNull @SuppressWarnings("unused") // used by field updater volatile TaskNode tail; /** * Queue size: *

    *
  • Bit 00..1F: current queue length
  • *
  • Bit 20..3F: queue limit
  • *
*/ @SuppressWarnings("unused") // used by field updater volatile long queueSize; /** * Active consumers: *
    *
  • Bit 00..19: current number of running threads
  • *
  • Bit 20..39: core pool size
  • *
  • Bit 40..59: maximum pool size
  • *
  • Bit 60: 1 = allow core thread timeout; 0 = disallow core thread timeout
  • *
  • Bit 61: 1 = shutdown requested; 0 = shutdown not requested
  • *
  • Bit 62: 1 = shutdown task interrupt requested; 0 = interrupt not requested
  • *
  • Bit 63: 1 = shutdown complete; 0 = shutdown not complete
  • *
*/ @SuppressWarnings("unused") // used by field updater volatile long threadStatus; /** * The thread keep-alive timeout value. */ volatile long timeoutNanos; /** * A resistance factor applied after the core pool is full; values applied here will cause that fraction * of submissions to create new threads when no idle thread is available. A value of {@code 0.0f} implies that * threads beyond the core size should be created as aggressively as threads within it; a value of {@code 1.0f} * implies that threads beyond the core size should never be created. */ volatile float growthResistance; /** * The handler for tasks which cannot be accepted by the executor. */ volatile Executor handoffExecutor; /** * The handler for uncaught exceptions which occur during user tasks. */ volatile Thread.UncaughtExceptionHandler exceptionHandler; /** * The termination task to execute when the thread pool exits. */ volatile Runnable terminationTask; // ======================================================= // Statistics fields and counters // ======================================================= /** * The peak number of threads ever created by this pool. */ @SuppressWarnings("unused") // used by field updater volatile int peakThreadCount; /** * The approximate peak queue size. */ @SuppressWarnings("unused") // used by field updater volatile int peakQueueSize; private final LongAdder submittedTaskCounter = new LongAdder(); private final LongAdder completedTaskCounter = new LongAdder(); private final LongAdder rejectedTaskCounter = new LongAdder(); private final LongAdder spinMisses = new LongAdder(); /** * The current active number of threads. */ @SuppressWarnings("unused") volatile int activeCount; // ======================================================= // Updaters // ======================================================= private static final AtomicReferenceFieldUpdater headUpdater = AtomicReferenceFieldUpdater.newUpdater(EnhancedQueueExecutor.class, TaskNode.class, "head"); private static final AtomicReferenceFieldUpdater tailUpdater = AtomicReferenceFieldUpdater.newUpdater(EnhancedQueueExecutor.class, TaskNode.class, "tail"); private static final AtomicLongFieldUpdater queueSizeUpdater = AtomicLongFieldUpdater.newUpdater(EnhancedQueueExecutor.class, "queueSize"); private static final AtomicLongFieldUpdater threadStatusUpdater = AtomicLongFieldUpdater.newUpdater(EnhancedQueueExecutor.class, "threadStatus"); private static final AtomicIntegerFieldUpdater peakThreadCountUpdater = AtomicIntegerFieldUpdater.newUpdater(EnhancedQueueExecutor.class, "peakThreadCount"); private static final AtomicIntegerFieldUpdater activeCountUpdater = AtomicIntegerFieldUpdater.newUpdater(EnhancedQueueExecutor.class, "activeCount"); private static final AtomicIntegerFieldUpdater peakQueueSizeUpdater = AtomicIntegerFieldUpdater.newUpdater(EnhancedQueueExecutor.class, "peakQueueSize"); // ======================================================= // Thread state field constants // ======================================================= private static final long TS_THREAD_CNT_MASK = 0b1111_1111_1111_1111_1111L; // 20 bits, can be shifted as needed // shift amounts private static final long TS_CURRENT_SHIFT = 0; private static final long TS_CORE_SHIFT = 20; private static final long TS_MAX_SHIFT = 40; private static final long TS_ALLOW_CORE_TIMEOUT = 1L << 60; private static final long TS_SHUTDOWN_REQUESTED = 1L << 61; private static final long TS_SHUTDOWN_INTERRUPT = 1L << 62; @SuppressWarnings("NumericOverflow") private static final long TS_SHUTDOWN_COMPLETE = 1L << 63; private static final int EXE_OK = 0; private static final int EXE_REJECT_QUEUE_FULL = 1; private static final int EXE_REJECT_SHUTDOWN = 2; private static final int EXE_CREATE_THREAD = 3; private static final int AT_YES = 0; private static final int AT_NO = 1; private static final int AT_SHUTDOWN = 2; // ======================================================= // Marker objects // ======================================================= static final QNode TERMINATE_COMPLETE = new TerminateWaiterNode(null); static final Runnable WAITING = new NullRunnable(); static final Runnable GAVE_UP = new NullRunnable(); static final Runnable ACCEPTED = new NullRunnable(); static final Runnable EXIT = new NullRunnable(); // ======================================================= // Constructor // ======================================================= static final AtomicInteger sequence = new AtomicInteger(1); EnhancedQueueExecutor(final Builder builder) { this.acc = getContext(); int maxSize = builder.getMaximumPoolSize(); int coreSize = Math.min(builder.getCorePoolSize(), maxSize); this.handoffExecutor = builder.getHandoffExecutor(); this.exceptionHandler = builder.getExceptionHandler(); this.threadFactory = builder.getThreadFactory(); this.terminationTask = builder.getTerminationTask(); this.growthResistance = builder.getGrowthResistance(); final long keepAliveTime = builder.getKeepAliveTime(TimeUnit.NANOSECONDS); // initial dead node head = tail = new TaskNode(null); // thread stat threadStatus = withCoreSize(withMaxSize(withAllowCoreTimeout(0L, builder.allowsCoreThreadTimeOut()), maxSize), coreSize); timeoutNanos = max(1L, keepAliveTime); queueSize = withMaxQueueSize(withCurrentQueueSize(0L, 0), builder.getMaximumQueueSize()); mxBean = new MXBeanImpl(); if (builder.isRegisterMBean()) { final String configuredName = builder.getMBeanName(); final String finalName = configuredName != null ? configuredName : "threadpool-" + sequence.getAndIncrement(); handle = doPrivileged(new PrivilegedAction() { public ObjectInstance run() { try { final Hashtable table = new Hashtable<>(); table.put("name", finalName); table.put("type", "thread-pool"); return ManagementFactory.getPlatformMBeanServer().registerMBean(mxBean, new ObjectName("jboss.threads", table)); } catch (Throwable ignored) { } return null; } }, acc); } else { handle = null; } } // ======================================================= // Builder // ======================================================= /** * The builder class for an {@code EnhancedQueueExecutor}. All the fields are initialized to sensible defaults for * a small thread pool. */ public static final class Builder { private ThreadFactory threadFactory = Executors.defaultThreadFactory(); private Runnable terminationTask = NullRunnable.getInstance(); private Executor handoffExecutor = DEFAULT_HANDLER; private Thread.UncaughtExceptionHandler exceptionHandler = JBossExecutors.loggingExceptionHandler(); private int coreSize = 16; private int maxSize = 64; private long keepAliveTime = 30; private TimeUnit keepAliveUnits = TimeUnit.SECONDS; private float growthResistance; private boolean allowCoreTimeOut; private int maxQueueSize = Integer.MAX_VALUE; private boolean registerMBean = REGISTER_MBEAN; private String mBeanName; /** * Construct a new instance. */ public Builder() {} /** * Get the configured thread factory. * * @return the configured thread factory (not {@code null}) */ public ThreadFactory getThreadFactory() { return threadFactory; } /** * Set the configured thread factory. * * @param threadFactory the configured thread factory (must not be {@code null}) * @return this builder */ public Builder setThreadFactory(final ThreadFactory threadFactory) { Assert.checkNotNullParam("threadFactory", threadFactory); this.threadFactory = threadFactory; return this; } /** * Get the termination task. By default, an empty {@code Runnable} is used. * * @return the termination task (not {@code null}) */ public Runnable getTerminationTask() { return terminationTask; } /** * Set the termination task. * * @param terminationTask the termination task (must not be {@code null}) * @return this builder */ public Builder setTerminationTask(final Runnable terminationTask) { Assert.checkNotNullParam("terminationTask", terminationTask); this.terminationTask = terminationTask; return this; } /** * Get the core pool size. This is the size below which new threads will always be created if no idle threads * are available. If the pool size reaches the core size but has not yet reached the maximum size, a resistance * factor will be applied to each task submission which determines whether the task should be queued or a new * thread started. * * @return the core pool size * @see EnhancedQueueExecutor#getCorePoolSize() */ public int getCorePoolSize() { return coreSize; } /** * Set the core pool size. If the configured maximum pool size is less than the configured core size, the * core size will be reduced to match the maximum size when the thread pool is constructed. * * @param coreSize the core pool size (must be greater than or equal to 0, and less than 2^20) * @return this builder * @see EnhancedQueueExecutor#setCorePoolSize(int) */ public Builder setCorePoolSize(final int coreSize) { Assert.checkMinimumParameter("coreSize", 0, coreSize); Assert.checkMaximumParameter("coreSize", TS_THREAD_CNT_MASK, coreSize); this.coreSize = coreSize; return this; } /** * Get the maximum pool size. This is the absolute upper limit to the size of the thread pool. * * @return the maximum pool size * @see EnhancedQueueExecutor#getMaximumPoolSize() */ public int getMaximumPoolSize() { return maxSize; } /** * Set the maximum pool size. If the configured maximum pool size is less than the configured core size, the * core size will be reduced to match the maximum size when the thread pool is constructed. * * @param maxSize the maximum pool size (must be greater than or equal to 0, and less than 2^20) * @return this builder * @see EnhancedQueueExecutor#setMaximumPoolSize(int) */ public Builder setMaximumPoolSize(final int maxSize) { Assert.checkMinimumParameter("maxSize", 0, maxSize); Assert.checkMaximumParameter("maxSize", TS_THREAD_CNT_MASK, maxSize); this.maxSize = maxSize; return this; } /** * Get the thread keep-alive time. This is the amount of time (in the configured time unit) that idle threads * will wait for a task before exiting. * * @param keepAliveUnits the time keepAliveUnits of the keep-alive time (must not be {@code null}) * @return the thread keep-alive time * @see EnhancedQueueExecutor#getKeepAliveTime(TimeUnit) */ public long getKeepAliveTime(TimeUnit keepAliveUnits) { Assert.checkNotNullParam("keepAliveUnits", keepAliveUnits); return keepAliveUnits.convert(keepAliveTime, this.keepAliveUnits); } /** * Set the thread keep-alive time. * * @param keepAliveTime the thread keep-alive time (must be greater than 0) * @param keepAliveUnits the time keepAliveUnits of the keep-alive time (must not be {@code null}) * @return this builder * @see EnhancedQueueExecutor#setKeepAliveTime(long, TimeUnit) */ public Builder setKeepAliveTime(final long keepAliveTime, final TimeUnit keepAliveUnits) { Assert.checkMinimumParameter("keepAliveTime", 1L, keepAliveTime); Assert.checkNotNullParam("keepAliveUnits", keepAliveUnits); this.keepAliveTime = keepAliveTime; this.keepAliveUnits = keepAliveUnits; return this; } /** * Get the thread pool growth resistance. This is the average fraction of submitted tasks that will be enqueued (instead * of causing a new thread to start) when there are no idle threads and the pool size is equal to or greater than * the core size (but still less than the maximum size). A value of {@code 0.0} indicates that tasks should * not be enqueued until the pool is completely full; a value of {@code 1.0} indicates that tasks should always * be enqueued until the queue is completely full. * * @return the thread pool growth resistance * @see EnhancedQueueExecutor#getGrowthResistance() */ public float getGrowthResistance() { return growthResistance; } /** * Set the thread pool growth resistance. * * @param growthResistance the thread pool growth resistance (must be in the range {@code 0.0f ≤ n ≤ 1.0f}) * @return this builder * @see #getGrowthResistance() * @see EnhancedQueueExecutor#setGrowthResistance(float) */ public Builder setGrowthResistance(final float growthResistance) { Assert.checkMinimumParameter("growthResistance", 0.0f, growthResistance); Assert.checkMaximumParameter("growthResistance", 1.0f, growthResistance); this.growthResistance = growthResistance; return this; } /** * Determine whether core threads are allowed to time out. A "core thread" is defined as any thread in the pool * when the pool size is below the pool's {@linkplain #getCorePoolSize() core pool size}. * * @return {@code true} if core threads are allowed to time out, {@code false} otherwise * @see EnhancedQueueExecutor#allowsCoreThreadTimeOut() */ public boolean allowsCoreThreadTimeOut() { return allowCoreTimeOut; } /** * Establish whether core threads are allowed to time out. A "core thread" is defined as any thread in the pool * when the pool size is below the pool's {@linkplain #getCorePoolSize() core pool size}. * * @param allowCoreTimeOut {@code true} if core threads are allowed to time out, {@code false} otherwise * @return this builder * @see EnhancedQueueExecutor#allowCoreThreadTimeOut(boolean) */ public Builder allowCoreThreadTimeOut(final boolean allowCoreTimeOut) { this.allowCoreTimeOut = allowCoreTimeOut; return this; } /** * Get the maximum queue size. If the queue is full and a task cannot be immediately accepted, rejection will result. * * @return the maximum queue size * @see EnhancedQueueExecutor#getMaximumQueueSize() */ public int getMaximumQueueSize() { return maxQueueSize; } /** * Set the maximum queue size. * * @param maxQueueSize the maximum queue size (must be ≥ 0) * @see EnhancedQueueExecutor#setMaximumQueueSize(int) */ public Builder setMaximumQueueSize(final int maxQueueSize) { Assert.checkMinimumParameter("maxQueueSize", 0, maxQueueSize); Assert.checkMaximumParameter("maxQueueSize", Integer.MAX_VALUE, maxQueueSize); this.maxQueueSize = maxQueueSize; return this; } /** * Get the handoff executor. * * @return the handoff executor (not {@code null}) */ public Executor getHandoffExecutor() { return handoffExecutor; } /** * Set the handoff executor. * * @param handoffExecutor the handoff executor (must not be {@code null}) * @return this builder */ public Builder setHandoffExecutor(final Executor handoffExecutor) { Assert.checkNotNullParam("handoffExecutor", handoffExecutor); this.handoffExecutor = handoffExecutor; return this; } /** * Get the uncaught exception handler. * * @return the uncaught exception handler (not {@code null}) */ public Thread.UncaughtExceptionHandler getExceptionHandler() { return exceptionHandler; } /** * Set the uncaught exception handler. * * @param exceptionHandler the uncaught exception handler (must not be {@code null}) * @return this builder */ public Builder setExceptionHandler(final Thread.UncaughtExceptionHandler exceptionHandler) { this.exceptionHandler = exceptionHandler; return this; } /** * Construct the executor from the configured parameters. * * @return the executor, which will be active and ready to accept tasks (not {@code null}) */ public EnhancedQueueExecutor build() { return new EnhancedQueueExecutor(this); } /** * Determine whether an MBean should automatically be registered for this pool. * * @return {@code true} if an MBean is to be auto-registered; {@code false} otherwise */ public boolean isRegisterMBean() { return registerMBean; } /** * Establish whether an MBean should automatically be registered for this pool. * * @param registerMBean {@code true} if an MBean is to be auto-registered; {@code false} otherwise * @return this builder */ public Builder setRegisterMBean(final boolean registerMBean) { this.registerMBean = registerMBean; return this; } /** * Get the overridden MBean name. * * @return the overridden MBean name, or {@code null} if a default name should be generated */ public String getMBeanName() { return mBeanName; } /** * Set the overridden MBean name. * * @param mBeanName the overridden MBean name, or {@code null} if a default name should be generated * @return this builder */ public Builder setMBeanName(final String mBeanName) { this.mBeanName = mBeanName; return this; } } // ======================================================= // ExecutorService // ======================================================= /** * Execute a task. * * @param runnable the task to execute (must not be {@code null}) */ public void execute(Runnable runnable) { Assert.checkNotNullParam("runnable", runnable); final Runnable realRunnable = JBossExecutors.classLoaderPreservingTaskUnchecked(runnable); int result; if (TAIL_LOCK) synchronized (tailLock) { result = tryExecute(realRunnable); } else { result = tryExecute(realRunnable); } boolean ok = false; if (result == EXE_OK) { // last check to ensure that there is at least one existent thread to avoid rare thread timeout race condition if (currentSizeOf(threadStatus) == 0 && tryAllocateThread(0.0f) == AT_YES && ! doStartThread(null)) { deallocateThread(); } if (UPDATE_STATISTICS) submittedTaskCounter.increment(); return; } else if (result == EXE_CREATE_THREAD) try { ok = doStartThread(realRunnable); } finally { if (! ok) deallocateThread(); } else { if (UPDATE_STATISTICS) rejectedTaskCounter.increment(); if (result == EXE_REJECT_SHUTDOWN) { rejectShutdown(realRunnable); } else { assert result == EXE_REJECT_QUEUE_FULL; rejectQueueFull(realRunnable); } } } /** * Request that shutdown be initiated for this thread pool. This is equivalent to calling * {@link #shutdown(boolean) shutdown(false)}; see that method for more information. */ public void shutdown() { shutdown(false); } /** * Attempt to stop the thread pool immediately by interrupting all running threads and de-queueing all pending * tasks. The thread pool might not be fully stopped when this method returns, if a currently running task * does not respect interruption. * * @return a list of pending tasks (not {@code null}) */ public List shutdownNow() { shutdown(true); final ArrayList list = new ArrayList<>(); TaskNode head = this.head; QNode headNext; for (;;) { headNext = head.getNext(); if (headNext instanceof TaskNode) { TaskNode taskNode = (TaskNode) headNext; if (compareAndSetHead(head, taskNode)) { if (! NO_QUEUE_LIMIT) decreaseQueueSize(); head = taskNode; list.add(taskNode.task); } // retry } else { // no more tasks; return list; } } } /** * Determine whether shutdown was requested on this thread pool. * * @return {@code true} if shutdown was requested, {@code false} otherwise */ public boolean isShutdown() { return isShutdownRequested(threadStatus); } /** * Determine whether shutdown has completed on this thread pool. * * @return {@code true} if shutdown has completed, {@code false} otherwise */ public boolean isTerminated() { return isShutdownComplete(threadStatus); } /** * Wait for the thread pool to complete termination. If the timeout expires before the thread pool is terminated, * {@code false} is returned. If the calling thread is interrupted before the thread pool is terminated, then * an {@link InterruptedException} is thrown. * * @param timeout the amount of time to wait (must be ≥ 0) * @param unit the unit of time to use for waiting (must not be {@code null}) * @return {@code true} if the thread pool terminated within the given timeout, {@code false} otherwise * @throws InterruptedException if the calling thread was interrupted before either the time period elapsed or the pool terminated successfully */ public boolean awaitTermination(final long timeout, final TimeUnit unit) throws InterruptedException { Assert.checkMinimumParameter("timeout", 0, timeout); Assert.checkNotNullParam("unit", unit); if (timeout > 0) { final Thread thread = Thread.currentThread(); if (runningThreads.contains(thread)) { throw Messages.msg.cannotAwaitWithin(); } final TerminateWaiterNode node = new TerminateWaiterNode(thread); // stick it on the queue QNode tail = this.tail; QNode tailNext; for (;;) { tailNext = tail.getNext(); if (tailNext == null) { if (tail.compareAndSetNext(null, node)) { // now we wait! break; } } else if (tailNext == TERMINATE_COMPLETE) { // nothing more to be done! return true; } else { if (UPDATE_TAIL && tailNext instanceof TaskNode) { assert tail instanceof TaskNode; // else tailNext couldn't possibly be a TaskNode compareAndSetTail(((TaskNode) tail), ((TaskNode) tailNext)); } tail = tailNext; } } try { parkNanos(this, unit.toNanos(timeout)); } finally { // prevent future spurious unparks without sabotaging the queue's integrity node.getAndClearThread(); } } if (Thread.interrupted()) throw new InterruptedException(); return isTerminated(); } // ======================================================= // Management // ======================================================= public StandardThreadPoolMXBean getThreadPoolMXBean() { return mxBean; } // ======================================================= // Other public API // ======================================================= /** * Initiate shutdown of this thread pool. After this method is called, no new tasks will be accepted. Once * the last task is complete, the thread pool will be terminated and its * {@linkplain Builder#setTerminationTask(Runnable) termination task} * will be called. Calling this method more than once has no additional effect, unless all previous calls * had the {@code interrupt} parameter set to {@code false} and the subsequent call sets it to {@code true}, in * which case all threads in the pool will be interrupted. * * @param interrupt {@code true} to request that currently-running tasks be interrupted; {@code false} otherwise */ public void shutdown(boolean interrupt) { long oldStatus, newStatus; // state change sh1: // threadStatus ← threadStatus | shutdown // succeeds: - // preconditions: // none (thread status may be in any state) // postconditions (succeed): // (always) ShutdownRequested set in threadStatus // (maybe) ShutdownInterrupted set in threadStatus (depends on parameter) // (maybe) ShutdownComplete set in threadStatus (if currentSizeOf() == 0) // (maybe) exit if no change // postconditions (fail): - // post-actions (fail): // repeat state change until success or return do { oldStatus = threadStatus; newStatus = withShutdownRequested(oldStatus); if (interrupt) newStatus = withShutdownInterrupt(newStatus); if (currentSizeOf(oldStatus) == 0) newStatus = withShutdownComplete(newStatus); if (newStatus == oldStatus) return; } while (! compareAndSetThreadStatus(oldStatus, newStatus)); assert oldStatus != newStatus; if (isShutdownRequested(newStatus) != isShutdownRequested(oldStatus)) { assert ! isShutdownRequested(oldStatus); // because it can only ever be set, not cleared // we initiated shutdown // clear out all consumers and append a dummy waiter node TaskNode tail = this.tail; QNode tailNext; // a marker to indicate that termination was requested final TerminateWaiterNode terminateNode = new TerminateWaiterNode(null); for (;;) { tailNext = tail.getNext(); if (tailNext instanceof TaskNode) { tail = (TaskNode) tailNext; } else if (tailNext instanceof PoolThreadNode || tailNext == null) { // remove the entire chain from this point PoolThreadNode node = (PoolThreadNode) tailNext; // state change sh2: // tail.next ← terminateNode(null) // succeeds: sh1 // preconditions: // threadStatus contains shutdown // tail(snapshot) is a task node // tail(snapshot).next is a (list of) pool thread node(s) or null // postconditions (succeed): // tail(snapshot).next is terminateNode(null) if (tail.compareAndSetNext(node, terminateNode)) { // got it! // state change sh3: // node.task ← EXIT // preconditions: // none (node task may be in any state) // postconditions (succeed): // task is EXIT // postconditions (fail): // no change (repeat loop) while (node != null) { node.compareAndSetTask(WAITING, EXIT); unpark(node.thread); node = node.getNext(); } // success; exit loop break; } // repeat loop (failed CAS) } else if (tailNext instanceof TerminateWaiterNode) { // theoretically impossible, but it means we have nothing else to do break; } else { throw Assert.unreachableCode(); } } } if (isShutdownInterrupt(newStatus) != isShutdownInterrupt(oldStatus)) { assert ! isShutdownInterrupt(oldStatus); // because it can only ever be set, not cleared // we initiated interrupt, so interrupt all currently active threads for (Thread thread : runningThreads) { thread.interrupt(); } } if (isShutdownComplete(newStatus) != isShutdownComplete(oldStatus)) { assert ! isShutdownComplete(oldStatus); // because it can only ever be set, not cleared completeTermination(); } } /** * Determine if this thread pool is in the process of terminating but has not yet completed. * * @return {@code true} if the thread pool is terminating, or {@code false} if the thread pool is not terminating or has completed termination */ public boolean isTerminating() { final long threadStatus = this.threadStatus; return isShutdownRequested(threadStatus) && ! isShutdownComplete(threadStatus); } /** * Start an idle core thread. Normally core threads are only begun when a task was submitted to the executor * but no thread is immediately available to handle the task. * * @return {@code true} if a core thread was started, or {@code false} if all core threads were already running or * if the thread failed to be created for some other reason */ public boolean prestartCoreThread() { if (tryAllocateThread(1.0f) != AT_YES) return false; if (doStartThread(null)) return true; deallocateThread(); return false; } /** * Start all core threads. Calls {@link #prestartCoreThread()} in a loop until it returns {@code false}. * * @return the number of core threads created */ public int prestartAllCoreThreads() { int cnt = 0; while (prestartCoreThread()) cnt ++; return cnt; } // ======================================================= // Tuning & configuration parameters (run time) // ======================================================= /** * Get the thread pool growth resistance. This is the average fraction of submitted tasks that will be enqueued (instead * of causing a new thread to start) when there are no idle threads and the pool size is equal to or greater than * the core size (but still less than the maximum size). A value of {@code 0.0} indicates that tasks should * not be enqueued until the pool is completely full; a value of {@code 1.0} indicates that tasks should always * be enqueued until the queue is completely full. * * @return the configured growth resistance factor * @see Builder#getGrowthResistance() Builder.getGrowthResistance() */ public float getGrowthResistance() { return growthResistance; } /** * Set the growth resistance factor. * * @param growthResistance the thread pool growth resistance (must be in the range {@code 0.0f ≤ n ≤ 1.0f}) * @see Builder#setGrowthResistance(float) Builder.setGrowthResistance() */ public void setGrowthResistance(final float growthResistance) { Assert.checkMinimumParameter("growthResistance", 0.0f, growthResistance); Assert.checkMaximumParameter("growthResistance", 1.0f, growthResistance); this.growthResistance = growthResistance; } /** * Get the core pool size. This is the size below which new threads will always be created if no idle threads * are available. If the pool size reaches the core size but has not yet reached the maximum size, a resistance * factor will be applied to each task submission which determines whether the task should be queued or a new * thread started. * * @return the core pool size * @see Builder#getCorePoolSize() Builder.getCorePoolSize() */ public int getCorePoolSize() { return coreSizeOf(threadStatus); } /** * Set the core pool size. If the configured maximum pool size is less than the configured core size, the * core size will be reduced to match the maximum size when the thread pool is constructed. * * @param corePoolSize the core pool size (must be greater than or equal to 0, and less than 2^20) * @see Builder#setCorePoolSize(int) Builder.setCorePoolSize() */ public void setCorePoolSize(final int corePoolSize) { Assert.checkMinimumParameter("corePoolSize", 0, corePoolSize); Assert.checkMaximumParameter("corePoolSize", TS_THREAD_CNT_MASK, corePoolSize); long oldVal, newVal; do { oldVal = threadStatus; if (corePoolSize > maxSizeOf(oldVal)) { // automatically bump up max size to match newVal = withCoreSize(withMaxSize(oldVal, corePoolSize), corePoolSize); } else { newVal = withCoreSize(oldVal, corePoolSize); } } while (! compareAndSetThreadStatus(oldVal, newVal)); if (maxSizeOf(newVal) < maxSizeOf(oldVal) || coreSizeOf(newVal) < coreSizeOf(oldVal)) { // poke all the threads to try to terminate any excess eagerly for (Thread activeThread : runningThreads) { unpark(activeThread); } } } /** * Get the maximum pool size. This is the absolute upper limit to the size of the thread pool. * * @return the maximum pool size * @see Builder#getMaximumPoolSize() Builder.getMaximumPoolSize() */ public int getMaximumPoolSize() { return maxSizeOf(threadStatus); } /** * Set the maximum pool size. If the configured maximum pool size is less than the configured core size, the * core size will be reduced to match the maximum size when the thread pool is constructed. * * @param maxPoolSize the maximum pool size (must be greater than or equal to 0, and less than 2^20) * @see Builder#setMaximumPoolSize(int) Builder.setMaximumPoolSize() */ public void setMaximumPoolSize(final int maxPoolSize) { Assert.checkMinimumParameter("maxPoolSize", 0, maxPoolSize); Assert.checkMaximumParameter("maxPoolSize", TS_THREAD_CNT_MASK, maxPoolSize); long oldVal, newVal; do { oldVal = threadStatus; if (maxPoolSize < coreSizeOf(oldVal)) { // automatically bump down core size to match newVal = withCoreSize(withMaxSize(oldVal, maxPoolSize), maxPoolSize); } else { newVal = withMaxSize(oldVal, maxPoolSize); } } while (! compareAndSetThreadStatus(oldVal, newVal)); if (maxSizeOf(newVal) < maxSizeOf(oldVal) || coreSizeOf(newVal) < coreSizeOf(oldVal)) { // poke all the threads to try to terminate any excess eagerly for (Thread activeThread : runningThreads) { unpark(activeThread); } } } /** * Determine whether core threads are allowed to time out. A "core thread" is defined as any thread in the pool * when the pool size is below the pool's {@linkplain #getCorePoolSize() core pool size}. * * @return {@code true} if core threads are allowed to time out, {@code false} otherwise * @see Builder#allowsCoreThreadTimeOut() Builder.allowsCoreThreadTimeOut() */ public boolean allowsCoreThreadTimeOut() { return isAllowCoreTimeout(threadStatus); } /** * Establish whether core threads are allowed to time out. A "core thread" is defined as any thread in the pool * when the pool size is below the pool's {@linkplain #getCorePoolSize() core pool size}. * * @param value {@code true} if core threads are allowed to time out, {@code false} otherwise * @see Builder#allowCoreThreadTimeOut(boolean) Builder.allowCoreThreadTimeOut() */ public void allowCoreThreadTimeOut(boolean value) { long oldVal, newVal; do { oldVal = threadStatus; newVal = withAllowCoreTimeout(oldVal, value); if (oldVal == newVal) return; } while (! compareAndSetThreadStatus(oldVal, newVal)); if (value) { // poke all the threads to try to terminate any excess eagerly for (Thread activeThread : runningThreads) { unpark(activeThread); } } } /** * Get the thread keep-alive time. This is the minimum length of time that idle threads should remain until they exit. * Unless core threads are allowed to time out, threads will only exit if the current thread count exceeds the core * limit. * * @param keepAliveUnits the unit in which the result should be expressed (must not be {@code null}) * @return the amount of time (will be greater than zero) * @see Builder#getKeepAliveTime(TimeUnit) Builder.getKeepAliveTime() */ public long getKeepAliveTime(TimeUnit keepAliveUnits) { Assert.checkNotNullParam("keepAliveUnits", keepAliveUnits); return keepAliveUnits.convert(timeoutNanos, TimeUnit.NANOSECONDS); } /** * Set the thread keep-alive time. This is the minimum length of time that idle threads should remain until they exit. * Unless core threads are allowed to time out, threads will only exit if the current thread count exceeds the core * limit. * * @param keepAliveTime the thread keep-alive time (must be > 0) * @param keepAliveUnits the unit in which the value is expressed (must not be {@code null}) * @see Builder#setKeepAliveTime(long, TimeUnit) Builder.setKeepAliveTime() */ public void setKeepAliveTime(final long keepAliveTime, final TimeUnit keepAliveUnits) { Assert.checkMinimumParameter("keepAliveTime", 1L, keepAliveTime); Assert.checkNotNullParam("keepAliveUnits", keepAliveUnits); timeoutNanos = max(1L, keepAliveUnits.toNanos(keepAliveTime)); } /** * Get the maximum queue size. If the queue is full and a task cannot be immediately accepted, rejection will result. * * @return the maximum queue size * @see Builder#getMaximumQueueSize() Builder.getMaximumQueueSize() */ public int getMaximumQueueSize() { return maxQueueSizeOf(queueSize); } /** * Set the maximum queue size. If the new maximum queue size is smaller than the current queue size, there is no * effect other than preventing tasks from being enqueued until the size decreases below the maximum again. * * @param maxQueueSize the maximum queue size (must be ≥ 0) * @see Builder#setMaximumQueueSize(int) Builder.setMaximumQueueSize() */ public void setMaximumQueueSize(final int maxQueueSize) { Assert.checkMinimumParameter("maxQueueSize", 0, maxQueueSize); Assert.checkMaximumParameter("maxQueueSize", Integer.MAX_VALUE, maxQueueSize); if (NO_QUEUE_LIMIT) return; long oldVal; do { oldVal = queueSize; } while (! compareAndSetQueueSize(oldVal, withMaxQueueSize(oldVal, maxQueueSize))); } /** * Get the executor to delegate to in the event of task rejection. * * @return the executor to delegate to in the event of task rejection (not {@code null}) */ public Executor getHandoffExecutor() { return handoffExecutor; } /** * Set the executor to delegate to in the event of task rejection. * * @param handoffExecutor the executor to delegate to in the event of task rejection (must not be {@code null}) */ public void setHandoffExecutor(final Executor handoffExecutor) { Assert.checkNotNullParam("handoffExecutor", handoffExecutor); this.handoffExecutor = handoffExecutor; } /** * Get the exception handler to use for uncaught exceptions. * * @return the exception handler to use for uncaught exceptions (not {@code null}) */ public Thread.UncaughtExceptionHandler getExceptionHandler() { return exceptionHandler; } /** * Set the exception handler to use for uncaught exceptions. * * @param exceptionHandler the exception handler to use for uncaught exceptions (must not be {@code null}) */ public void setExceptionHandler(final Thread.UncaughtExceptionHandler exceptionHandler) { Assert.checkNotNullParam("exceptionHandler", exceptionHandler); this.exceptionHandler = exceptionHandler; } /** * Set the termination task, overwriting any previous setting. * * @param terminationTask the termination task, or {@code null} to perform no termination task */ public void setTerminationTask(final Runnable terminationTask) { this.terminationTask = terminationTask; } // ======================================================= // Statistics & metrics API // ======================================================= /** * Get an estimate of the current queue size. * * @return an estimate of the current queue size */ public int getQueueSize() { return currentQueueSizeOf(queueSize); } /** * Get an estimate of the peak number of threads that the pool has ever held. * * @return an estimate of the peak number of threads that the pool has ever held */ public int getLargestPoolSize() { return peakThreadCount; } /** * Get an estimate of the number of threads which are currently doing work on behalf of the thread pool. * * @return the active count estimate */ public int getActiveCount() { return activeCount; } /** * Get an estimate of the peak size of the queue. * * @return an estimate of the peak size of the queue */ public int getLargestQueueSize() { return peakQueueSize; } /** * Get an estimate of the total number of tasks ever submitted to this thread pool. * * @return an estimate of the total number of tasks ever submitted to this thread pool */ public long getSubmittedTaskCount() { return submittedTaskCounter.longValue(); } /** * Get an estimate of the total number of tasks ever rejected by this thread pool for any reason. * * @return an estimate of the total number of tasks ever rejected by this thread pool */ public long getRejectedTaskCount() { return rejectedTaskCounter.longValue(); } /** * Get an estimate of the number of tasks completed by this thread pool. * * @return an estimate of the number of tasks completed by this thread pool */ public long getCompletedTaskCount() { return completedTaskCounter.longValue(); } /** * Get an estimate of the current number of active threads in the pool. * * @return an estimate of the current number of active threads in the pool */ public int getPoolSize() { return currentSizeOf(threadStatus); } // ======================================================= // Pooled thread body // ======================================================= final class ThreadBody implements Runnable { private Runnable initialTask; ThreadBody(final Runnable initialTask) { this.initialTask = initialTask; } /** * Execute the body of the thread. On entry the thread is added to the {@link #runningThreads} set, and on * exit it is removed. */ public void run() { final Thread currentThread = Thread.currentThread(); final Object headLock = EnhancedQueueExecutor.this.headLock; final LongAdder spinMisses = EnhancedQueueExecutor.this.spinMisses; runningThreads.add(currentThread); // run the initial task doRunTask(getAndClearInitialTask()); // clear TCCL JBossExecutors.clearContextClassLoader(currentThread); // main loop QNode node; processingQueue: for (;;) { if (HEAD_LOCK) synchronized (headLock) { node = getOrAddNode(); } else { node = getOrAddNode(); } if (node instanceof TaskNode) { // task node was removed doRunTask(((TaskNode) node).getAndClearTask()); continue; } else if (node instanceof PoolThreadNode) { // pool thread node was added final PoolThreadNode newNode = (PoolThreadNode) node; // at this point, we are registered into the queue long start = System.nanoTime(); long elapsed = 0L; waitingForTask: for (;;) { Runnable task = newNode.getTask(); assert task != ACCEPTED && task != GAVE_UP; if (task != WAITING && task != EXIT) { if (newNode.compareAndSetTask(task, ACCEPTED)) { // we have a task to run, so run it and then abandon the node doRunTask(task); // rerun outer continue processingQueue; } // we had a task to run, but we failed to CAS it for some reason, so retry if (UPDATE_STATISTICS) spinMisses.increment(); continue waitingForTask; } else { final long timeoutNanos = EnhancedQueueExecutor.this.timeoutNanos; long oldVal = threadStatus; if (elapsed >= timeoutNanos || task == EXIT || currentSizeOf(oldVal) > maxSizeOf(oldVal)) { // try to exit this thread, if we are allowed if (task == EXIT || isShutdownRequested(oldVal) || isAllowCoreTimeout(oldVal) || currentSizeOf(oldVal) > coreSizeOf(oldVal) ) { if (newNode.compareAndSetTask(task, GAVE_UP)) { for (;;) { if (tryDeallocateThread(oldVal)) { // clear to exit. runningThreads.remove(currentThread); return; } if (UPDATE_STATISTICS) spinMisses.increment(); oldVal = threadStatus; } //throw Assert.unreachableCode(); } continue waitingForTask; } else { if (elapsed >= timeoutNanos) { park(EnhancedQueueExecutor.this); } else { parkNanos(EnhancedQueueExecutor.this, timeoutNanos - elapsed); } Thread.interrupted(); elapsed = System.nanoTime() - start; // retry inner continue waitingForTask; } //throw Assert.unreachableCode(); } else { assert task == WAITING; parkNanos(EnhancedQueueExecutor.this, timeoutNanos - elapsed); Thread.interrupted(); elapsed = System.nanoTime() - start; // retry inner continue waitingForTask; } //throw Assert.unreachableCode(); } //throw Assert.unreachableCode(); } // :waitingForTask //throw Assert.unreachableCode(); } else { assert node instanceof TerminateWaiterNode; // we're shutting down! runningThreads.remove(currentThread); deallocateThread(); return; } //throw Assert.unreachableCode(); } // :processingQueue //throw Assert.unreachableCode(); } private QNode getOrAddNode() { TaskNode head; QNode headNext; for (;;) { head = EnhancedQueueExecutor.this.head; headNext = head.getNext(); if (headNext instanceof TaskNode) { TaskNode taskNode = (TaskNode) headNext; if (compareAndSetHead(head, taskNode)) { if (! NO_QUEUE_LIMIT) decreaseQueueSize(); return taskNode; } } else if (headNext instanceof PoolThreadNode || headNext == null) { PoolThreadNode newNode; newNode = new PoolThreadNode((PoolThreadNode) headNext, Thread.currentThread()); if (head.compareAndSetNext(headNext, newNode)) { return newNode; } } else { assert headNext instanceof TerminateWaiterNode; return headNext; } if (UPDATE_STATISTICS) spinMisses.increment(); } } private Runnable getAndClearInitialTask() { try { return initialTask; } finally { this.initialTask = null; } } void doRunTask(final Runnable task) { if (task != null) { if (isShutdownInterrupt(threadStatus)) { Thread.currentThread().interrupt(); } else { Thread.interrupted(); } if (UPDATE_STATISTICS) incrementActiveCount(); safeRun(task); if (UPDATE_STATISTICS) { decrementActiveCount(); completedTaskCounter.increment(); } } } } // ======================================================= // Thread starting // ======================================================= /** * Allocate a new thread. * * @param growthResistance the growth resistance to apply * @return {@code AT_YES} if a thread is allocated; {@code AT_NO} if a thread was not allocated; {@code AT_SHUTDOWN} if the pool is being shut down */ int tryAllocateThread(final float growthResistance) { int oldSize; long oldStat; for (;;) { oldStat = threadStatus; if (isShutdownRequested(oldStat)) { return AT_SHUTDOWN; } oldSize = currentSizeOf(oldStat); if (oldSize >= maxSizeOf(oldStat)) { // max threads already reached return AT_NO; } if (oldSize >= coreSizeOf(oldStat) && oldSize > 0) { // core threads are reached; check resistance factor (if no threads are running, then always start a thread) if (growthResistance != 0.0f && (growthResistance == 1.0f || ThreadLocalRandom.current().nextFloat() < growthResistance)) { // do not create a thread this time return AT_NO; } } // try to increase final int newSize = oldSize + 1; // state change ex3: // threadStatus.size ← threadStatus(snapshot).size + 1 // cannot succeed: sh1 // succeeds: - // preconditions: // ! threadStatus(snapshot).shutdownRequested // threadStatus(snapshot).size < threadStatus(snapshot).maxSize // threadStatus(snapshot).size < threadStatus(snapshot).coreSize || random < growthResistance // post-actions (fail): // retry whole loop if (compareAndSetThreadStatus(oldStat, withCurrentSize(oldStat, newSize))) { // increment peak thread count if (UPDATE_STATISTICS) { int oldVal; do { oldVal = peakThreadCount; if (oldVal >= newSize) break; } while (! compareAndSetPeakThreadCount(oldVal, newSize)); } return AT_YES; } if (UPDATE_STATISTICS) spinMisses.increment(); } } /** * Roll back a thread allocation, possibly terminating the pool. Only call after {@link #tryAllocateThread(float)} returns {@link #AT_YES}. */ void deallocateThread() { long oldStat; do { oldStat = threadStatus; } while (! tryDeallocateThread(oldStat)); } /** * Try to roll back a thread allocation, possibly running the termination task if the pool would be terminated * by last thread exit. * * @param oldStat the {@code threadStatus} to CAS * @return {@code true} if the thread was deallocated, or {@code false} to retry with a new {@code oldStat} */ boolean tryDeallocateThread(long oldStat) { assert ! holdsLock(headLock) && ! holdsLock(tailLock); // roll back our thread allocation attempt // state change ex4: // threadStatus.size ← threadStatus.size - 1 // succeeds: ex3 // preconditions: // threadStatus.size > 0 long newStat = withCurrentSize(oldStat, currentSizeOf(oldStat) - 1); if (currentSizeOf(newStat) == 0 && isShutdownRequested(oldStat)) { newStat = withShutdownComplete(newStat); } if (! compareAndSetThreadStatus(oldStat, newStat)) return false; if (isShutdownComplete(newStat)) { completeTermination(); } return true; } /** * Start an allocated thread. * * @param runnable the task or {@code null} * @return {@code true} if the thread was started, {@code false} otherwise * @throws RejectedExecutionException if {@code runnable} is not {@code null} and the thread could not be created or started */ boolean doStartThread(Runnable runnable) throws RejectedExecutionException { assert ! holdsLock(headLock) && ! holdsLock(tailLock); Thread thread; try { thread = threadFactory.newThread(new ThreadBody(runnable)); } catch (Throwable t) { if (runnable != null) { if (UPDATE_STATISTICS) rejectedTaskCounter.increment(); rejectException(runnable, t); } return false; } if (thread == null) { if (runnable != null) { if (UPDATE_STATISTICS) rejectedTaskCounter.increment(); rejectNoThread(runnable); } return false; } try { thread.start(); } catch (Throwable t) { if (runnable != null) { if (UPDATE_STATISTICS) rejectedTaskCounter.increment(); rejectException(runnable, t); } return false; } return true; } // ======================================================= // Task submission // ======================================================= private int tryExecute(final Runnable runnable) { QNode tailNext; TaskNode tail = this.tail; final int result; for (;;) { tailNext = tail.getNext(); if (tailNext instanceof TaskNode) { TaskNode tailNextTaskNode; do { if (UPDATE_STATISTICS) spinMisses.increment(); tailNextTaskNode = (TaskNode) tailNext; // retry tail = tailNextTaskNode; tailNext = tail.getNext(); } while (tailNext instanceof TaskNode); // opportunistically update for the possible benefit of other threads if (UPDATE_TAIL) compareAndSetTail(tail, tailNextTaskNode); } // we've progressed to the first non-task node, as far as we can see assert ! (tailNext instanceof TaskNode); if (tailNext instanceof PoolThreadNode) { final QNode tailNextNext = tailNext.getNext(); // state change ex1: // tail(snapshot).next ← tail(snapshot).next(snapshot).next(snapshot) // succeeds: - // cannot succeed: sh2 // preconditions: // tail(snapshot) is a dead TaskNode // tail(snapshot).next is PoolThreadNode // tail(snapshot).next.next* is PoolThreadNode or null // additional success postconditions: - // failure postconditions: - // post-actions (succeed): // run state change ex2 // post-actions (fail): // retry with new tail(snapshot) if (tail.compareAndSetNext(tailNext, tailNextNext)) { PoolThreadNode consumerNode = (PoolThreadNode) tailNext; // state change ex2: // tail(snapshot).next(snapshot).task ← runnable // succeeds: ex1 // preconditions: // tail(snapshot).next(snapshot).task = WAITING // post-actions (succeed): // unpark thread and return // post-actions (fail): // retry outer with new tail(snapshot) if (consumerNode.compareAndSetTask(WAITING, runnable)) { unpark(consumerNode.getThread()); result = EXE_OK; break; } // otherwise the consumer gave up or was exited already, so fall out and... } // retry with new tail(snapshot) as was foretold tail = this.tail; if (UPDATE_STATISTICS) spinMisses.increment(); } else if (tailNext == null) { // no consumers available; maybe we can start one int tr = tryAllocateThread(growthResistance); if (tr == AT_YES) { result = EXE_CREATE_THREAD; break; } if (tr == AT_SHUTDOWN) { result = EXE_REJECT_SHUTDOWN; break; } assert tr == AT_NO; // no; try to enqueue if (! NO_QUEUE_LIMIT && ! increaseQueueSize()) { // queue is full // OK last effort to create a thread, disregarding growth limit tr = tryAllocateThread(0.0f); if (tr == AT_YES) { result = EXE_CREATE_THREAD; break; } if (tr == AT_SHUTDOWN) { result = EXE_REJECT_SHUTDOWN; break; } assert tr == AT_NO; result = EXE_REJECT_QUEUE_FULL; break; } // queue size increased successfully; we can add to the list TaskNode node = new TaskNode(runnable); // state change ex5: // tail(snapshot).next ← new task node // cannot succeed: sh2 // preconditions: // tail(snapshot).next = null // ex3 failed precondition // queue size increased to accommodate node // postconditions (success): // tail(snapshot).next = new task node if (tail.compareAndSetNext(null, node)) { // try to update tail to the new node; if this CAS fails then tail already points at past the node // this is because tail can only ever move forward, and the task list is always strongly connected compareAndSetTail(tail, node); result = EXE_OK; break; } // we failed; we have to drop the queue size back down again to compensate before we can retry if (! NO_QUEUE_LIMIT) decreaseQueueSize(); // retry with new tail(snapshot) tail = this.tail; if (UPDATE_STATISTICS) spinMisses.increment(); } else { // no consumers are waiting and the tail(snapshot).next node is non-null and not a task node, therefore it must be a... assert tailNext instanceof TerminateWaiterNode; // shutting down result = EXE_REJECT_SHUTDOWN; break; } } return result; } // ======================================================= // Termination task // ======================================================= void completeTermination() { assert ! holdsLock(headLock) && ! holdsLock(tailLock); // be kind and un-interrupt the thread for the termination task Thread.interrupted(); final Runnable terminationTask = this.terminationTask; this.terminationTask = null; safeRun(terminationTask); // notify all waiters QNode tail = EnhancedQueueExecutor.this.tail; QNode tailNext = tail.getAndSetNext(TERMINATE_COMPLETE); while (tailNext != null) { // state change ct1: // tail(snapshot).next(snapshot).thread ← null // succeeds: sh2 // preconditions: // threadStatus is shutdown (because sh1 ≺ … ≺ ct1) // postconditions: - // post-actions: // unpark(twn) if (tailNext instanceof TerminateWaiterNode) { unpark(((TerminateWaiterNode) tailNext).getAndClearThread()); } tailNext = tailNext.getNext(); } final ObjectInstance handle = this.handle; if (handle != null) { doPrivileged(new PrivilegedAction() { public Void run() { try { ManagementFactory.getPlatformMBeanServer().unregisterMBean(handle.getObjectName()); } catch (Throwable ignored) { } return null; } }, acc); } } // ======================================================= // Compare-and-set operations // ======================================================= void incrementActiveCount() { activeCountUpdater.incrementAndGet(this); } void decrementActiveCount() { activeCountUpdater.decrementAndGet(this); } boolean compareAndSetThreadStatus(final long expect, final long update) { return threadStatusUpdater.compareAndSet(this, expect, update); } boolean compareAndSetHead(final TaskNode expect, final TaskNode update) { return headUpdater.compareAndSet(this, expect, update); } boolean compareAndSetPeakThreadCount(final int expect, final int update) { return peakThreadCountUpdater.compareAndSet(this, expect, update); } boolean compareAndSetPeakQueueSize(final int expect, final int update) { return peakQueueSizeUpdater.compareAndSet(this, expect, update); } boolean compareAndSetQueueSize(final long expect, final long update) { return queueSizeUpdater.compareAndSet(this, expect, update); } void compareAndSetTail(final TaskNode expect, final TaskNode update) { tailUpdater.compareAndSet(this, expect, update); } // ======================================================= // Queue size operations // ======================================================= boolean increaseQueueSize() { long oldVal = queueSize; int oldSize = currentQueueSizeOf(oldVal); if (oldSize >= maxQueueSizeOf(oldVal)) { // reject return false; } int newSize = oldSize + 1; while (! compareAndSetQueueSize(oldVal, withCurrentQueueSize(oldVal, newSize))) { if (UPDATE_STATISTICS) spinMisses.increment(); oldVal = queueSize; oldSize = currentQueueSizeOf(oldVal); if (oldSize >= maxQueueSizeOf(oldVal)) { // reject return false; } newSize = oldSize + 1; } if (UPDATE_STATISTICS) { do { // oldSize now represents the old peak size oldSize = peakQueueSize; if (newSize <= oldSize) break; } while (! compareAndSetPeakQueueSize(oldSize, newSize)); } return true; } void decreaseQueueSize() { long oldVal; oldVal = queueSize; assert currentQueueSizeOf(oldVal) > 0; while (! compareAndSetQueueSize(oldVal, withCurrentQueueSize(oldVal, currentQueueSizeOf(oldVal) - 1))) { if (UPDATE_STATISTICS) spinMisses.increment(); oldVal = queueSize; assert currentQueueSizeOf(oldVal) > 0; } } // ======================================================= // Inline Functions // ======================================================= static int currentQueueSizeOf(long queueSize) { return (int) (queueSize & 0x7fff_ffff); } static long withCurrentQueueSize(long queueSize, int current) { assert current >= 0; return queueSize & 0xffff_ffff_0000_0000L | current; } static int maxQueueSizeOf(long queueSize) { return (int) (queueSize >>> 32 & 0x7fff_ffff); } static long withMaxQueueSize(long queueSize, int max) { assert max >= 0; return queueSize & 0xffff_ffffL | (long)max << 32; } static int coreSizeOf(long status) { return (int) (status >>> TS_CORE_SHIFT & TS_THREAD_CNT_MASK); } static int maxSizeOf(long status) { return (int) (status >>> TS_MAX_SHIFT & TS_THREAD_CNT_MASK); } static int currentSizeOf(long status) { return (int) (status >>> TS_CURRENT_SHIFT & TS_THREAD_CNT_MASK); } static long withCoreSize(long status, int newCoreSize) { assert 0 <= newCoreSize && newCoreSize <= TS_THREAD_CNT_MASK; return status & ~(TS_THREAD_CNT_MASK << TS_CORE_SHIFT) | (long)newCoreSize << TS_CORE_SHIFT; } static long withCurrentSize(long status, int newCurrentSize) { assert 0 <= newCurrentSize && newCurrentSize <= TS_THREAD_CNT_MASK; return status & ~(TS_THREAD_CNT_MASK << TS_CURRENT_SHIFT) | (long)newCurrentSize << TS_CURRENT_SHIFT; } static long withMaxSize(long status, int newMaxSize) { assert 0 <= newMaxSize && newMaxSize <= TS_THREAD_CNT_MASK; return status & ~(TS_THREAD_CNT_MASK << TS_MAX_SHIFT) | (long)newMaxSize << TS_MAX_SHIFT; } static long withShutdownRequested(final long status) { return status | TS_SHUTDOWN_REQUESTED; } static long withShutdownComplete(final long status) { return status | TS_SHUTDOWN_COMPLETE; } static long withShutdownInterrupt(final long status) { return status | TS_SHUTDOWN_INTERRUPT; } static long withAllowCoreTimeout(final long status, final boolean allowed) { return allowed ? status | TS_ALLOW_CORE_TIMEOUT : status & ~TS_ALLOW_CORE_TIMEOUT; } static boolean isShutdownRequested(final long status) { return (status & TS_SHUTDOWN_REQUESTED) != 0; } static boolean isShutdownComplete(final long status) { return (status & TS_SHUTDOWN_COMPLETE) != 0; } static boolean isShutdownInterrupt(final long threadStatus) { return (threadStatus & TS_SHUTDOWN_INTERRUPT) != 0; } static boolean isAllowCoreTimeout(final long oldVal) { return (oldVal & TS_ALLOW_CORE_TIMEOUT) != 0; } // ======================================================= // Static configuration // ======================================================= private static boolean readBooleanProperty(String name, boolean defVal) { return Boolean.parseBoolean(readProperty(name, Boolean.toString(defVal))); } private static String readProperty(String name, String defVal) { final SecurityManager sm = System.getSecurityManager(); if (sm != null) { return doPrivileged(new PrivilegedAction() { public String run() { return readPropertyRaw(name, defVal); } }); } else { return readPropertyRaw(name, defVal); } } private static String readPropertyRaw(final String name, final String defVal) { return System.getProperty("jboss.threads.eqe." + name, defVal); } // ======================================================= // Utilities // ======================================================= void safeRun(final Runnable task) { assert ! holdsLock(headLock) && ! holdsLock(tailLock); try { if (task != null) task.run(); } catch (Throwable t) { try { exceptionHandler.uncaughtException(Thread.currentThread(), t); } catch (Throwable ignored) { // nothing else we can safely do here } } finally { // clear TCCL JBossExecutors.clearContextClassLoader(Thread.currentThread()); // clear interrupt status Thread.interrupted(); } } void rejectException(final Runnable task, final Throwable cause) { try { handoffExecutor.execute(task); } catch (Throwable t) { t.addSuppressed(cause); throw t; } } void rejectNoThread(final Runnable task) { try { handoffExecutor.execute(task); } catch (Throwable t) { t.addSuppressed(new RejectedExecutionException("No threads available")); throw t; } } void rejectQueueFull(final Runnable task) { try { handoffExecutor.execute(task); } catch (Throwable t) { t.addSuppressed(new RejectedExecutionException("Queue is full")); throw t; } } void rejectShutdown(final Runnable task) { try { handoffExecutor.execute(task); } catch (Throwable t) { t.addSuppressed(new RejectedExecutionException("Executor is being shut down")); throw t; } } // ======================================================= // Node classes // ======================================================= @Contended abstract static class QNode { // in 9, use VarHandle private static final AtomicReferenceFieldUpdater nextUpdater = AtomicReferenceFieldUpdater.newUpdater(QNode.class, QNode.class, "next"); @SuppressWarnings("unused") private volatile QNode next; QNode(final QNode next) { this.next = next; } boolean compareAndSetNext(QNode expect, QNode update) { return nextUpdater.compareAndSet(this, expect, update); } QNode getNext() { return nextUpdater.get(this); } QNode getAndSetNext(final QNode node) { return nextUpdater.getAndSet(this, node); } } @Contended static final class PoolThreadNode extends QNode { private final Thread thread; @SuppressWarnings("unused") private volatile Runnable task; private static final AtomicReferenceFieldUpdater taskUpdater = AtomicReferenceFieldUpdater.newUpdater(PoolThreadNode.class, Runnable.class, "task"); PoolThreadNode(final PoolThreadNode next, final Thread thread) { super(next); this.thread = thread; task = WAITING; } Thread getThread() { return thread; } boolean compareAndSetTask(final Runnable expect, final Runnable update) { return taskUpdater.compareAndSet(this, expect, update); } Runnable getTask() { return taskUpdater.get(this); } PoolThreadNode getNext() { return (PoolThreadNode) super.getNext(); } } @Contended static final class TerminateWaiterNode extends QNode { private volatile Thread thread; TerminateWaiterNode(final Thread thread) { // always start with a {@code null} next super(null); this.thread = thread; } Thread getAndClearThread() { // doesn't have to be particularly atomic try { return thread; } finally { thread = null; } } TerminateWaiterNode getNext() { return (TerminateWaiterNode) super.getNext(); } } @Contended static final class TaskNode extends QNode { volatile Runnable task; TaskNode(final Runnable task) { // we always start task nodes with a {@code null} next super(null); this.task = task; } Runnable getAndClearTask() { try { return task; } finally { this.task = null; } } } // ======================================================= // Management bean implementation // ======================================================= final class MXBeanImpl implements StandardThreadPoolMXBean { MXBeanImpl() { } public float getGrowthResistance() { return EnhancedQueueExecutor.this.getGrowthResistance(); } public void setGrowthResistance(final float value) { EnhancedQueueExecutor.this.setGrowthResistance(value); } public boolean isGrowthResistanceSupported() { return true; } public int getCorePoolSize() { return EnhancedQueueExecutor.this.getCorePoolSize(); } public void setCorePoolSize(final int corePoolSize) { EnhancedQueueExecutor.this.setCorePoolSize(corePoolSize); } public boolean isCorePoolSizeSupported() { return true; } public boolean prestartCoreThread() { return EnhancedQueueExecutor.this.prestartCoreThread(); } public int prestartAllCoreThreads() { return EnhancedQueueExecutor.this.prestartAllCoreThreads(); } public boolean isCoreThreadPrestartSupported() { return true; } public int getMaximumPoolSize() { return EnhancedQueueExecutor.this.getMaximumPoolSize(); } public void setMaximumPoolSize(final int maxPoolSize) { EnhancedQueueExecutor.this.setMaximumPoolSize(maxPoolSize); } public int getPoolSize() { return EnhancedQueueExecutor.this.getPoolSize(); } public int getLargestPoolSize() { return EnhancedQueueExecutor.this.getLargestPoolSize(); } public int getActiveCount() { return EnhancedQueueExecutor.this.getActiveCount(); } public boolean isAllowCoreThreadTimeOut() { return EnhancedQueueExecutor.this.allowsCoreThreadTimeOut(); } public void setAllowCoreThreadTimeOut(final boolean value) { EnhancedQueueExecutor.this.allowCoreThreadTimeOut(value); } public long getKeepAliveTimeSeconds() { return EnhancedQueueExecutor.this.getKeepAliveTime(TimeUnit.SECONDS); } public void setKeepAliveTimeSeconds(final long seconds) { EnhancedQueueExecutor.this.setKeepAliveTime(seconds, TimeUnit.SECONDS); } public int getMaximumQueueSize() { return EnhancedQueueExecutor.this.getMaximumQueueSize(); } public void setMaximumQueueSize(final int size) { EnhancedQueueExecutor.this.setMaximumQueueSize(size); } public int getQueueSize() { return EnhancedQueueExecutor.this.getQueueSize(); } public int getLargestQueueSize() { return EnhancedQueueExecutor.this.getLargestQueueSize(); } public boolean isQueueBounded() { return ! NO_QUEUE_LIMIT; } public boolean isQueueSizeModifiable() { return ! NO_QUEUE_LIMIT; } public boolean isShutdown() { return EnhancedQueueExecutor.this.isShutdown(); } public boolean isTerminating() { return EnhancedQueueExecutor.this.isTerminating(); } public boolean isTerminated() { return EnhancedQueueExecutor.this.isTerminated(); } public long getSubmittedTaskCount() { return EnhancedQueueExecutor.this.getSubmittedTaskCount(); } public long getRejectedTaskCount() { return EnhancedQueueExecutor.this.getRejectedTaskCount(); } public long getCompletedTaskCount() { return EnhancedQueueExecutor.this.getCompletedTaskCount(); } public long getSpinMissCount() { return EnhancedQueueExecutor.this.spinMisses.longValue(); } } } jboss-threads-2.3.2.Final/src/main/java/org/jboss/threads/EventListener.java000066400000000000000000000021161325274360100267500ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2017 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.threads; /** * An event listener which handles a single event and accepts an attachment of some type. * * @author David M. Lloyd */ public interface EventListener extends java.util.EventListener { /** * Handle the event. * * @param attachment the attachment */ void handleEvent(A attachment); } jboss-threads-2.3.2.Final/src/main/java/org/jboss/threads/ExceptionLoggingExecutor.java000066400000000000000000000031401325274360100311430ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2017 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.threads; import org.jboss.logging.Logger; class ExceptionLoggingExecutor implements DirectExecutor { private final DirectExecutor delegate; private final Logger log; private final Logger.Level level; ExceptionLoggingExecutor(final DirectExecutor delegate, final Logger log, final Logger.Level level) { this.delegate = delegate; this.log = log; this.level = level; } ExceptionLoggingExecutor(final DirectExecutor delegate, final Logger log) { this(delegate, log, Logger.Level.ERROR); } public void execute(final Runnable command) { try { delegate.execute(command); } catch (Throwable t) { log.logf(level, t, "Exception thrown from thread task"); } } public String toString() { return String.format("%s to \"%s\" -> %s", super.toString(), log.getName(), delegate); } } jboss-threads-2.3.2.Final/src/main/java/org/jboss/threads/ExecutionInterruptedException.java000066400000000000000000000052041325274360100322320ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2017 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.threads; import java.util.concurrent.RejectedExecutionException; /** * Thrown when a {@link java.util.concurrent.Executor#execute(Runnable)} submission is interrupted before the task could be accepted. If * this exception is thrown, the thread's {@code interrupted} flag will also be set. */ @Deprecated public class ExecutionInterruptedException extends RejectedExecutionException { private static final long serialVersionUID = -8420751681898632287L; /** * Constructs a {@code ExecutionInterruptedException} with no detail message. The cause is not initialized, and may * subsequently be initialized by a call to {@link #initCause(Throwable) initCause}. */ public ExecutionInterruptedException() { } /** * Constructs a {@code ExecutionInterruptedException} with the specified detail message. The cause is not initialized, * and may subsequently be initialized by a call to {@link #initCause(Throwable) initCause}. * * @param msg the detail message */ public ExecutionInterruptedException(final String msg) { super(msg); } /** * Constructs a {@code ExecutionInterruptedException} with the specified cause. The detail message is set to: *
(cause == null ? null : cause.toString())
* (which typically contains the class and detail message of {@code cause}). * * @param cause the cause (which is saved for later retrieval by the {@link #getCause()} method) */ public ExecutionInterruptedException(final Throwable cause) { super(cause); } /** * Constructs a {@code ExecutionInterruptedException} with the specified detail message and cause. * * @param msg the detail message * @param cause the cause (which is saved for later retrieval by the {@link #getCause()} method) */ public ExecutionInterruptedException(final String msg, final Throwable cause) { super(msg, cause); } } jboss-threads-2.3.2.Final/src/main/java/org/jboss/threads/ExecutionTimedOutException.java000066400000000000000000000050011325274360100314520ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2017 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.threads; import java.util.concurrent.RejectedExecutionException; /** * Thrown when an execute-with-timeout method is called and the timeout elapsed before a task could be accepted. */ @Deprecated public class ExecutionTimedOutException extends RejectedExecutionException { private static final long serialVersionUID = 6577491781534695133L; /** * Constructs a {@code ExecutionTimedOutException} with no detail message. The cause is not initialized, and may * subsequently be initialized by a call to {@link #initCause(Throwable) initCause}. */ public ExecutionTimedOutException() { } /** * Constructs a {@code ExecutionTimedOutException} with the specified detail message. The cause is not initialized, and * may subsequently be initialized by a call to {@link #initCause(Throwable) initCause}. * * @param msg the detail message */ public ExecutionTimedOutException(final String msg) { super(msg); } /** * Constructs a {@code ExecutionTimedOutException} with the specified cause. The detail message is set to: *
(cause == null ? null : cause.toString())
* (which typically contains the class and detail message of {@code cause}). * * @param cause the cause (which is saved for later retrieval by the {@link #getCause()} method) */ public ExecutionTimedOutException(final Throwable cause) { super(cause); } /** * Constructs a {@code ExecutionTimedOutException} with the specified detail message and cause. * * @param msg the detail message * @param cause the cause (which is saved for later retrieval by the {@link #getCause()} method) */ public ExecutionTimedOutException(final String msg, final Throwable cause) { super(msg, cause); } } jboss-threads-2.3.2.Final/src/main/java/org/jboss/threads/ExecutorTask.java000066400000000000000000000022361325274360100266050ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2017 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.threads; class ExecutorTask implements Runnable { private final DirectExecutor executor; private final Runnable task; ExecutorTask(final DirectExecutor executor, final Runnable task) { this.executor = executor; this.task = task; } public void run() { executor.execute(task); } public String toString() { return String.format("%s (Task %s via %s)", super.toString(), task, executor); } } jboss-threads-2.3.2.Final/src/main/java/org/jboss/threads/HandoffRejectedExecutionHandler.java000066400000000000000000000024461325274360100323640ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2017 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.threads; import java.util.concurrent.RejectedExecutionHandler; import java.util.concurrent.Executor; import java.util.concurrent.ThreadPoolExecutor; class HandoffRejectedExecutionHandler implements RejectedExecutionHandler { private final Executor target; HandoffRejectedExecutionHandler(final Executor target) { this.target = target; } public void rejectedExecution(final Runnable r, final ThreadPoolExecutor executor) { target.execute(r); } public String toString() { return String.format("%s -> %s", super.toString(), target); } } jboss-threads-2.3.2.Final/src/main/java/org/jboss/threads/InitializingExecutor.java000066400000000000000000000024231325274360100303330ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2017 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ 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 (init task=%s) -> %s", super.toString(), initializer, delegate); } } jboss-threads-2.3.2.Final/src/main/java/org/jboss/threads/InterruptHandler.java000066400000000000000000000022611325274360100274540ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2017 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.threads; /** * A thread interrupt handler. Called when a thread's {@code interrupt()} method is invoked. The handler should * not throw an exception; otherwise user code might end up in an unexpected state. */ public interface InterruptHandler { /** * Handle an interrupt condition on the given thread. This method should not throw an exception. * * @param thread the thread which was interrupted */ void handleInterrupt(Thread thread); } jboss-threads-2.3.2.Final/src/main/java/org/jboss/threads/JBossExecutors.java000066400000000000000000001056541325274360100271160ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2017 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.threads; import java.lang.reflect.Field; import java.util.concurrent.Executor; import java.util.concurrent.ExecutorService; import java.util.concurrent.RejectedExecutionException; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.RejectedExecutionHandler; import java.util.concurrent.ThreadFactory; import java.util.concurrent.ScheduledExecutorService; import java.util.Collection; import java.security.PrivilegedAction; import java.security.AccessController; import java.security.Permission; import org.jboss.logging.Logger; import org.wildfly.common.Assert; import sun.misc.Unsafe; /** * JBoss thread- and executor-related utility and factory methods. */ 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 COPY_CONTEXT_CLASSLOADER_PERMISSION = new RuntimePermission("copyClassLoader"); private static final DirectExecutorService DIRECT_EXECUTOR_SERVICE = new DelegatingDirectExecutorService(SimpleDirectExecutor.INSTANCE); private static final DirectExecutorService REJECTING_EXECUTOR_SERVICE = new DelegatingDirectExecutorService(RejectingExecutor.INSTANCE); private static final DirectExecutorService DISCARDING_EXECUTOR_SERVICE = new DelegatingDirectExecutorService(DiscardingExecutor.INSTANCE); @Deprecated private static final BlockingExecutor BLOCKING_DIRECT_EXECUTOR = new DelegatingDirectBlockingExecutor(SimpleDirectExecutor.INSTANCE); @Deprecated private static final BlockingExecutor BLOCKING_REJECTING_EXECUTOR = new DelegatingDirectBlockingExecutor(RejectingExecutor.INSTANCE); @Deprecated private static final BlockingExecutor BLOCKING_DISCARDING_EXECUTOR = new DelegatingDirectBlockingExecutor(DiscardingExecutor.INSTANCE); // ================================================== // DIRECT EXECUTORS // ================================================== /** * Get the direct executor. This executor will immediately run any task it is given, and propagate back any * run-time exceptions thrown. * * @return the direct executor instance */ public static DirectExecutor directExecutor() { return SimpleDirectExecutor.INSTANCE; } /** * Get the direct executor service. This executor will immediately run any task it is given, and propagate back any * run-time exceptions thrown. It cannot be shut down. * * @return the direct executor service instance */ public static DirectExecutorService directExecutorService() { return DIRECT_EXECUTOR_SERVICE; } /** * Get the rejecting executor. This executor will reject any task submitted to it. * * @return the rejecting executor instance */ public static DirectExecutor rejectingExecutor() { return RejectingExecutor.INSTANCE; } /** * Get a rejecting executor. This executor will reject any task submitted to it with the given message. * * @param message the reject message * @return the rejecting executor instance */ public static DirectExecutor rejectingExecutor(final String message) { return new RejectingExecutor(message); } /** * Get the rejecting executor service. This executor will reject any task submitted to it. It cannot be shut down. * * @return the rejecting executor service instance */ public static DirectExecutorService rejectingExecutorService() { return REJECTING_EXECUTOR_SERVICE; } /** * Get the rejecting executor service. This executor will reject any task submitted to it with the given message. * It cannot be shut down. * * @param message the reject message * @return the rejecting executor service instance */ public static DirectExecutorService rejectingExecutorService(final String message) { return protectedDirectExecutorService(rejectingExecutor(message)); } /** * Get the discarding executor. This executor will silently discard any task submitted to it. * * @return the discarding executor instance */ public static DirectExecutor discardingExecutor() { return DiscardingExecutor.INSTANCE; } /** * Get the discarding executor service. This executor will silently discard any task submitted to it. It cannot * be shut down. * * @return the discarding executor service instance */ public static DirectExecutorService discardingExecutorService() { return DISCARDING_EXECUTOR_SERVICE; } /** * Create a direct executor which runs with the privileges given by the current access control context. * * @param delegate the executor to delegate to at the privileged level * @return the new direct executor */ public static DirectExecutor privilegedExecutor(final DirectExecutor delegate) { return new PrivilegedExecutor(delegate); } /** * Create a direct executor which runs tasks with the given context class loader. * * @param delegate the executor to delegate to * @param taskClassLoader the context class loader to use * @return the new direct executor */ public static DirectExecutor contextClassLoaderExecutor(final DirectExecutor delegate, final ClassLoader taskClassLoader) { return new ContextClassLoaderExecutor(taskClassLoader, delegate); } /** * Create a direct executor which changes the thread name for the duration of a task. * * @param delegate the executor to delegate to * @param newName the thread name to use * @return the new direct executor */ public static DirectExecutor threadNameExecutor(final DirectExecutor delegate, final String newName) { return new ThreadNameExecutor(newName, delegate); } /** * Create a direct executor which changes the thread name for the duration of a task using a formatted name. * The thread must be a {@link JBossThread}. * * @param delegate the executor to delegate to * @param newName the thread name to use * @return the new direct executor */ public static DirectExecutor threadFormattedNameExecutor(final DirectExecutor delegate, final String newName) { return new ThreadFormattedNameExecutor(newName, delegate); } /** * Create a direct executor which adds a note to the thread name for the duration of a task. * * @param delegate the executor to delegate to * @param notation the note to use * @return the new direct executor */ public static DirectExecutor threadNameNotateExecutor(final DirectExecutor delegate, final String notation) { return new ThreadNameNotatingExecutor(notation, delegate); } /** * Create a direct executor which consumes and logs errors that are thrown. * * @param delegate the executor to delegate to * @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 Logger log) { return new ExceptionLoggingExecutor(delegate, log); } /** * Create a direct executor which consumes and logs errors that are thrown. * * @param delegate the executor to delegate to * @param log the logger to which exceptions are written * @param level the level at which to log exceptions * @return the new direct executor */ public static DirectExecutor exceptionLoggingExecutor(final DirectExecutor delegate, final Logger log, final Logger.Level level) { return new ExceptionLoggingExecutor(delegate, log, level); } /** * 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 all thread-local * data after each task completes (regardless of outcome). You must have the {@link RuntimePermission}{@code ("modifyThread")} * permission to use this method. * * @param delegate the delegate direct executor * @return a resetting executor * @throws SecurityException if the caller does not have the {@link RuntimePermission}{@code ("modifyThread")} permission */ public static DirectExecutor resettingExecutor(final DirectExecutor delegate) throws SecurityException { return cleanupExecutor(delegate, threadLocalResetter()); } /** * Create an executor which runs the given initialization task before running its given task. * * @param delegate the delegate direct executor * @param initializer the initialization task * @return an initializing executor */ public static DirectExecutor initializingExecutor(final DirectExecutor delegate, final Runnable initializer) { return new InitializingExecutor(initializer, delegate); } /** * Create an executor which runs the given cleanup task after running its given task. * * @param delegate the delegate direct executor * @param cleaner the cleanup task * @return an initializing executor */ public static DirectExecutor cleanupExecutor(final DirectExecutor delegate, final Runnable cleaner) { return new CleanupExecutor(cleaner, delegate); } // ================================================== // DIRECT BLOCKING EXECUTORS // ================================================== /** * Get an executor which executes tasks in the current thread, which implements {@code BlockingExecutor}. * * @return the blocking direct executor */ @Deprecated public static BlockingExecutor blockingDirectExecutor() { return BLOCKING_DIRECT_EXECUTOR; } /** * Get an executor which discards all tasks, which implements {@code BlockingExecutor}. * * @return the executor */ @Deprecated public static BlockingExecutor blockingDiscardingExecutor() { return BLOCKING_DISCARDING_EXECUTOR; } /** * Get an executor which rejects all tasks, which implements {@code BlockingExecutor}. * * @return the executor */ @Deprecated public static BlockingExecutor blockingRejectingExecutor() { return BLOCKING_REJECTING_EXECUTOR; } // ================================================== // EXECUTORS // ================================================== /** * An executor which delegates to another executor, wrapping each task in a task wrapper. * * @param taskWrapper the task wrapper * @param delegate the delegate executor * @return a wrapping executor */ public static Executor wrappingExecutor(final DirectExecutor taskWrapper, final Executor delegate) { return executor(wrappingExecutor(delegate), taskWrapper); } /** * An executor which delegates to the given direct executor, but implements the blocking executor interface. * Since direct executors always execute tasks in the current thread, no blocking is possible; therefore the * methods of BlockingExecutors always succeed or fail instantly. * * @param delegate the delegate direct executor * @return the blocking executor */ @Deprecated public static BlockingExecutor directBlockingExecutor(final DirectExecutor delegate) { return new DelegatingDirectBlockingExecutor(delegate); } /** * Create a wrapping executor for a delegate executor which creates an {@link #executorTask(DirectExecutor, Runnable)} for * each task. * * @param delegate the delegate executor * @return the wrapping executor */ public static WrappingExecutor wrappingExecutor(final Executor delegate) { return new DelegatingWrappingExecutor(delegate); } /** * An executor which delegates to a wrapping 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 executor(final WrappingExecutor delegate, final DirectExecutor taskWrapper) { return new DelegatingWrappedExecutor(delegate, taskWrapper); } /** * Create an executor that executes each task in a new thread. * * @param factory the thread factory to use * @return the executor * @deprecated Use {@link EnhancedQueueExecutor} instead. */ @Deprecated public static BlockingExecutor threadFactoryExecutor(final ThreadFactory factory) { return new ThreadFactoryExecutor(factory, Integer.MAX_VALUE, false, directExecutor()); } /** * Create an executor that executes each task in a new thread. By default up to the given number of threads may run * concurrently, after which new tasks will be rejected. * * @param factory the thread factory to use * @param maxThreads the maximum number of allowed threads * @return the executor * @deprecated Use {@link EnhancedQueueExecutor} instead. */ @Deprecated public static BlockingExecutor threadFactoryExecutor(final ThreadFactory factory, final int maxThreads) { return new ThreadFactoryExecutor(factory, maxThreads, false, directExecutor()); } /** * Create an executor that executes each task in a new thread. By default up to the given number of threads may run * concurrently, after which the caller will block or new tasks will be rejected, according to the setting of the * {@code blocking} parameter. * * @param factory the thread factory to use * @param maxThreads the maximum number of allowed threads * @param blocking {@code true} if the submitter should block when the maximum number of threads has been reached * @return the executor * @deprecated Use {@link EnhancedQueueExecutor} instead. */ @Deprecated public static BlockingExecutor threadFactoryExecutor(final ThreadFactory factory, final int maxThreads, final boolean blocking) { return new ThreadFactoryExecutor(factory, maxThreads, blocking, directExecutor()); } /** * Create an executor that executes each task in a new thread. By default up to the given number of threads may run * concurrently, after which the caller will block or new tasks will be rejected, according to the setting of the * {@code blocking} parameter. * * @param factory the thread factory to use * @param maxThreads the maximum number of allowed threads * @param blocking {@code true} if the submitter should block when the maximum number of threads has been reached * @param taskExecutor the executor which should run each task * @return the executor * @deprecated Use {@link EnhancedQueueExecutor} instead. */ @Deprecated public static BlockingExecutor threadFactoryExecutor(final ThreadFactory factory, final int maxThreads, final boolean blocking, final DirectExecutor taskExecutor) { return new ThreadFactoryExecutor(factory, maxThreads, blocking, taskExecutor); } // ================================================== // 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(); private static final RejectedExecutionHandler DISCARD_POLICY = new ThreadPoolExecutor.DiscardPolicy(); /** * Get the abort policy for a {@link java.util.concurrent.ThreadPoolExecutor}. * * @return the abort policy * @see java.util.concurrent.ThreadPoolExecutor.AbortPolicy */ public static RejectedExecutionHandler abortPolicy() { return ABORT_POLICY; } /** * Get the caller-runs policy for a {@link java.util.concurrent.ThreadPoolExecutor}. * * @return the caller-runs policy * @see java.util.concurrent.ThreadPoolExecutor.CallerRunsPolicy */ public static RejectedExecutionHandler callerRunsPolicy() { return CALLER_RUNS_POLICY; } /** * Get the discard-oldest policy for a {@link java.util.concurrent.ThreadPoolExecutor}. * * @return the discard-oldest policy * @see java.util.concurrent.ThreadPoolExecutor.DiscardOldestPolicy */ public static RejectedExecutionHandler discardOldestPolicy() { return DISCARD_OLDEST_POLICY; } /** * Get the discard policy for a {@link java.util.concurrent.ThreadPoolExecutor}. * * @return the discard policy * @see java.util.concurrent.ThreadPoolExecutor.DiscardPolicy */ public static RejectedExecutionHandler discardPolicy() { return DISCARD_POLICY; } /** * Get a handoff policy for a {@link java.util.concurrent.ThreadPoolExecutor}. The returned instance will * delegate to another executor in the event that the task is rejected. * * @param target the target executor * @return the new handoff policy implementation */ public static RejectedExecutionHandler handoffPolicy(final Executor target) { return new HandoffRejectedExecutionHandler(target); } // ================================================== // PROTECTED EXECUTOR SERVICE WRAPPERS // ================================================== @Deprecated public static BlockingExecutor protectedBlockingExecutor(final BlockingExecutor target) { return new DelegatingBlockingExecutor(target); } /** * Wrap an executor with an {@code ExecutorService} instance which supports all the features of {@code ExecutorService} * except for shutting down the executor. * * @param target the target executor * @return the executor service */ public static ExecutorService protectedExecutorService(final Executor target) { return new DelegatingExecutorService(target); } /** * Wrap a direct executor with an {@code DirectExecutorService} instance which supports all the features of {@code ExecutorService} * except for shutting down the executor. * * @param target the target executor * @return the executor service */ public static DirectExecutorService protectedDirectExecutorService(final DirectExecutor target) { return new DelegatingDirectExecutorService(target); } /** * Wrap a scheduled executor with a {@code ScheduledExecutorService} instance which supports all the features of * {@code ScheduledExecutorService} except for shutting down the executor. * * @param target the target executor * @return the executor service */ public static ScheduledExecutorService protectedScheduledExecutorService(final ScheduledExecutorService target) { return new DelegatingScheduledExecutorService(target); } /** * Wrap a blocking executor with an {@code BlockingExecutorService} instance which supports all the features of * {@code BlockingExecutorService} except for shutting down the executor. * * @param target the target executor * @return the executor service */ @Deprecated public static BlockingExecutorService protectedBlockingExecutorService(final BlockingExecutor target) { return new DelegatingBlockingExecutorService(target); } // ================================================== // THREAD FACTORIES // ================================================== /** * 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 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 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"; } }; // ================================================== // RUNNABLES // ================================================== private static final Runnable NULL_RUNNABLE = NullRunnable.getInstance(); private static final Runnable THREAD_LOCAL_RESETTER; /** * 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 ExecutorTask(executor, task); } /** * Create a task that is a composite of several other tasks. * * @param runnables the tasks * @return the composite task */ public static Runnable compositeTask(final Runnable... runnables) { return new CompositeTask(runnables.clone()); } /** * Create a task that delegates to the given task, preserving the context classloader which was in effect when * this method was invoked. * * @param delegate the delegate runnable * @return the wrapping runnable * @throws SecurityException if a security manager exists and the caller does not have the {@code "copyClassLoader"} * {@link RuntimePermission}. */ public static Runnable classLoaderPreservingTask(final Runnable delegate) throws SecurityException { final SecurityManager sm = System.getSecurityManager(); if (sm != null) { sm.checkPermission(COPY_CONTEXT_CLASSLOADER_PERMISSION); } return classLoaderPreservingTaskUnchecked(delegate); } static final ClassLoader SAFE_CL; static { ClassLoader safeClassLoader = JBossExecutors.class.getClassLoader(); if (safeClassLoader == null) { safeClassLoader = ClassLoader.getSystemClassLoader(); } if (safeClassLoader == null) { safeClassLoader = new ClassLoader() { }; } SAFE_CL = safeClassLoader; } static Runnable classLoaderPreservingTaskUnchecked(final Runnable delegate) { Assert.checkNotNullParam("delegate", delegate); return new ContextClassLoaderSavingRunnable(getContextClassLoader(Thread.currentThread()), delegate); } static final Unsafe unsafe; static final long contextClassLoaderOffs; static { unsafe = AccessController.doPrivileged(new PrivilegedAction() { public Unsafe run() { try { final Field field = Unsafe.class.getDeclaredField("theUnsafe"); field.setAccessible(true); return (Unsafe) field.get(null); } catch (IllegalAccessException e) { throw new IllegalAccessError(e.getMessage()); } catch (NoSuchFieldException e) { throw new NoSuchFieldError(e.getMessage()); } } }); try { contextClassLoaderOffs = unsafe.objectFieldOffset(Thread.class.getDeclaredField("contextClassLoader")); } catch (NoSuchFieldException e) { throw new NoSuchFieldError(e.getMessage()); } THREAD_LOCAL_RESETTER = ThreadLocalResetter.getInstance(); } /** * Privileged method to get the context class loader of the given thread. * * @param thread the thread to introspect * @return the context class loader */ static ClassLoader getContextClassLoader(final Thread thread) { return (ClassLoader) unsafe.getObject(thread, contextClassLoaderOffs); } /** * Privileged method to get and set the context class loader of the given thread. * * @param thread the thread to introspect * @param newClassLoader the new context class loader * @return the old context class loader */ static ClassLoader getAndSetContextClassLoader(final Thread thread, final ClassLoader newClassLoader) { try { return getContextClassLoader(thread); } finally { setContextClassLoader(thread, newClassLoader); } } /** * Privileged method to set the context class loader of the given thread. * * @param thread the thread to introspect * @param classLoader the new context class loader */ static void setContextClassLoader(final Thread thread, final ClassLoader classLoader) { unsafe.putObject(thread, contextClassLoaderOffs, classLoader); } /** * Privileged method to clear the context class loader of the given thread to a safe non-{@code null} value. * * @param thread the thread to introspect */ static void clearContextClassLoader(final Thread thread) { unsafe.putObject(thread, contextClassLoaderOffs, SAFE_CL); } /** * Create a task that is a composite of several other tasks. * * @param runnables the tasks * @return the composite task */ public static Runnable compositeTask(final Collection runnables) { return new CompositeTask(runnables.toArray(new Runnable[runnables.size()])); } static void checkAccess(Permission permission) { final SecurityManager sm = System.getSecurityManager(); if (sm != null) { sm.checkPermission(permission); } } // ================================================== // UNCAUGHT EXCEPTION HANDLERS // ================================================== /** * Get an uncaught exception handler which logs to the given logger. * * @param log the logger * @return the handler */ public static Thread.UncaughtExceptionHandler loggingExceptionHandler(final Logger log) { return new LoggingUncaughtExceptionHandler(log); } /** * Get an uncaught exception handler which logs to the given logger. * * @param categoryName the name of the logger category to log to * @return the handler */ public static Thread.UncaughtExceptionHandler loggingExceptionHandler(final String categoryName) { return new LoggingUncaughtExceptionHandler(Logger.getLogger(categoryName)); } private static final Thread.UncaughtExceptionHandler LOGGING_HANDLER = loggingExceptionHandler(THREAD_ERROR_LOGGER); /** * Get an uncaught exception handler which logs to the default error logger. * * @return the handler */ public static Thread.UncaughtExceptionHandler loggingExceptionHandler() { return LOGGING_HANDLER; } private static void logError(final R runnable, final Throwable t, final String method) { THREAD_ERROR_LOGGER.errorf(t, "Notifier %s() method invocation failed for task %s", method, runnable); } private static void started(TaskNotifier notifier, R runnable, A attachment) { try { notifier.started(runnable, attachment); } catch (Throwable t) { logError(runnable, t, "started"); } } private static void finished(TaskNotifier notifier, R runnable, A attachment) { try { notifier.finished(runnable, attachment); } catch (Throwable t) { logError(runnable, t, "finished"); } } private static void failed(TaskNotifier notifier, Throwable reason, R runnable, A attachment) { try { notifier.failed(runnable, reason, attachment); } catch (Throwable t) { logError(runnable, t, "failed"); } } /** * Run a task through the given direct executor, invoking the given notifier with the given attachment. * * @param task the task * @param directExecutor the executor * @param notifier the notifier * @param attachment the attachment * @param the task type * @param
the attachment type */ public static void run(R task, DirectExecutor directExecutor, TaskNotifier notifier, A attachment) { started(notifier, task, attachment); boolean ok = false; try { directExecutor.execute(task); ok = true; } catch (RuntimeException t) { failed(notifier, t, task, attachment); throw t; } catch (Error t) { failed(notifier, t, task, attachment); throw t; } catch (Throwable t) { failed(notifier, t, task, attachment); throw Messages.msg.unknownThrowable(t); } finally { if (ok) finished(notifier, task, attachment); } } /** * Run a task, invoking the given notifier with the given attachment. * * @param task the task * @param notifier the notifier * @param attachment the attachment * @param the task type * @param the attachment type */ public static void run(R task, TaskNotifier notifier, A attachment) { run(task, directExecutor(), notifier, attachment); } /** * Get a notifying runnable wrapper for a task. The notifier will be invoked when the task is run. * * @param task the task * @param notifier the notifier * @param attachment the attachment * @param the task type * @param the attachment type * @return the wrapping runnable */ public static Runnable notifyingRunnable(R task, TaskNotifier notifier, A attachment) { return new NotifyingRunnable(task, notifier, attachment); } /** * Get a notifying direct executor. The notifier will be invoked when each task is run. * * @param delegate the executor which will actually run the task * @param notifier the notifier * @param attachment the attachment * @param the attachment type * @return the direct executor */ public static DirectExecutor notifyingDirectExecutor(DirectExecutor delegate, TaskNotifier notifier, A attachment) { return new NotifyingDirectExecutor(delegate, notifier, attachment); } /** * Execute a task uninterruptibly. * * @param executor the executor to delegate to * @param task the task to execute * @throws RejectedExecutionException if the task was rejected by the executor */ public static void executeUninterruptibly(Executor executor, Runnable task) throws RejectedExecutionException { boolean intr = Thread.interrupted(); try { for (;;) { try { executor.execute(task); return; } catch (ExecutionInterruptedException e) { intr |= Thread.interrupted(); } } } finally { if (intr) { Thread.currentThread().interrupt(); } } } /** * Get an executor which executes tasks uninterruptibly in the event of blocking. * * @param delegate the delegate executor * @return the uninterruptible executor */ public static Executor uninterruptibleExecutor(final Executor delegate) { if (delegate instanceof UninterruptibleExecutor) { return delegate; } else { return new UninterruptibleExecutor(delegate); } } /** * Create a builder for a dependent task. * * @param executor the executor to use * @param task the task to run when all dependencies are met * @return the builder */ public static DependencyTaskBuilder dependencyTaskBuilder(final Executor executor, final Runnable task) { return new DependencyTaskBuilder(executor, task); } } jboss-threads-2.3.2.Final/src/main/java/org/jboss/threads/JBossScheduledThreadPoolExecutor.java000066400000000000000000000106271325274360100325310ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2017 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.threads; import java.util.concurrent.RejectedExecutionHandler; import java.util.concurrent.ScheduledThreadPoolExecutor; import java.util.concurrent.ThreadFactory; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; import org.jboss.threads.management.ThreadPoolExecutorMBean; public final class JBossScheduledThreadPoolExecutor extends ScheduledThreadPoolExecutor implements ThreadPoolExecutorMBean, ShutdownListenable { private final SimpleShutdownListenable shutdownListenable = new SimpleShutdownListenable(); private final AtomicInteger rejectCount = new AtomicInteger(); public JBossScheduledThreadPoolExecutor(int corePoolSize) { super(corePoolSize); setRejectedExecutionHandler(super.getRejectedExecutionHandler()); } public JBossScheduledThreadPoolExecutor(int corePoolSize, ThreadFactory threadFactory) { super(corePoolSize, threadFactory); setRejectedExecutionHandler(super.getRejectedExecutionHandler()); } public JBossScheduledThreadPoolExecutor(int corePoolSize, RejectedExecutionHandler handler) { super(corePoolSize); setRejectedExecutionHandler(handler); } public JBossScheduledThreadPoolExecutor(int corePoolSize, ThreadFactory threadFactory, RejectedExecutionHandler handler) { super(corePoolSize, threadFactory); setRejectedExecutionHandler(handler); } public long getKeepAliveTime() { return getKeepAliveTime(TimeUnit.MILLISECONDS); } public void setKeepAliveTime(final long milliseconds) { super.setKeepAliveTime(milliseconds, TimeUnit.MILLISECONDS); super.allowCoreThreadTimeOut(milliseconds < Long.MAX_VALUE); } public void setKeepAliveTime(final long time, final TimeUnit unit) { super.setKeepAliveTime(time, unit); super.allowCoreThreadTimeOut(time < Long.MAX_VALUE); } public int getRejectedCount() { return rejectCount.get(); } public int getCurrentThreadCount() { return getActiveCount(); } public int getLargestThreadCount() { return getLargestPoolSize(); } public int getMaxThreads() { return getCorePoolSize(); } public void setMaxThreads(final int newSize) { setCorePoolSize(newSize); } public RejectedExecutionHandler getRejectedExecutionHandler() { return ((CountingRejectHandler)super.getRejectedExecutionHandler()).getDelegate(); } public void setRejectedExecutionHandler(final RejectedExecutionHandler handler) { super.setRejectedExecutionHandler(new CountingRejectHandler(handler)); } /** {@inheritDoc} */ public int getQueueSize() { return this.getQueue().size(); } /** {@inheritDoc} */ public void addShutdownListener(final EventListener shutdownListener, final A attachment) { shutdownListenable.addShutdownListener(shutdownListener, attachment); } protected void terminated() { shutdownListenable.shutdown(); } private final class CountingRejectHandler implements RejectedExecutionHandler { private final RejectedExecutionHandler delegate; public CountingRejectHandler(final RejectedExecutionHandler delegate) { this.delegate = delegate; } public RejectedExecutionHandler getDelegate() { return delegate; } public void rejectedExecution(final Runnable r, final ThreadPoolExecutor executor) { rejectCount.incrementAndGet(); if (isShutdown()) { throw Messages.msg.shutDownInitiated(); } delegate.rejectedExecution(r, executor); } } } jboss-threads-2.3.2.Final/src/main/java/org/jboss/threads/JBossThread.java000066400000000000000000000627241325274360100263440ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2017 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.threads; import java.security.PrivilegedAction; import java.security.PrivilegedExceptionAction; import java.util.concurrent.Callable; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.locks.LockSupport; import org.wildfly.common.Assert; import org.wildfly.common.function.ExceptionBiConsumer; import org.wildfly.common.function.ExceptionBiFunction; import org.wildfly.common.function.ExceptionConsumer; import org.wildfly.common.function.ExceptionFunction; import org.wildfly.common.function.ExceptionObjIntConsumer; import org.wildfly.common.function.ExceptionObjLongConsumer; import org.wildfly.common.function.ExceptionRunnable; import org.wildfly.common.function.ExceptionSupplier; import org.wildfly.common.function.Functions; /** * A JBoss thread. Supports logging and extra operations. */ public class JBossThread extends Thread { static { Version.getVersionString(); } private volatile InterruptHandler interruptHandler; private ThreadNameInfo threadNameInfo; /** * The thread is maybe interrupted. Possible transitions: *
    *
  • {@link #STATE_INTERRUPT_DEFERRED}
  • *
  • {@link #STATE_INTERRUPT_IN_PROGRESS}
  • *
*/ private static final int STATE_MAYBE_INTERRUPTED = 0; /** * The thread is not interrupted, and interrupts will be deferred. Possible transitions: *
    *
  • {@link #STATE_MAYBE_INTERRUPTED}
  • *
  • {@link #STATE_INTERRUPT_PENDING}
  • *
*/ private static final int STATE_INTERRUPT_DEFERRED = 1; /** * The thread is not interrupted, but there is an interrupt pending for once deferral is ended. Possible transitions: *
    *
  • {@link #STATE_INTERRUPT_IN_PROGRESS}
  • *
*/ private static final int STATE_INTERRUPT_PENDING = 2; /** * The thread is in the process of executing interruption logic. If the thread attempts to defer interrupts * during this phase, it will block until the interruption logic is complete. */ private static final int STATE_INTERRUPT_IN_PROGRESS = 3; private final AtomicInteger stateRef = new AtomicInteger(); /** * Construct a new instance. * * @param target the runnable target * @see Thread#Thread(Runnable) */ public JBossThread(final Runnable target) { super(target); } /** * Construct a new instance. * * @param target the runnable target * @param name the initial thread name * @see Thread#Thread(Runnable, String) */ public JBossThread(final Runnable target, final String name) { super(target, name); } /** * Construct a new instance. * * @param group the parent thread group * @param target the runnable target * @see Thread#Thread(ThreadGroup, Runnable) * @throws SecurityException if the current thread cannot create a thread in the specified thread group */ public JBossThread(final ThreadGroup group, final Runnable target) throws SecurityException { super(group, target); } /** * Construct a new instance. * * @param group the parent thread group * @param target the runnable target * @param name the initial thread name * @see Thread#Thread(ThreadGroup,Runnable,String) * @throws SecurityException if the current thread cannot create a thread in the specified thread group */ public JBossThread(final ThreadGroup group, final Runnable target, final String name) throws SecurityException { super(group, target, name); } /** * Construct a new instance. * * @param group the parent thread group * @param target the runnable target * @param name the initial thread name * @see Thread#Thread(ThreadGroup,Runnable,String,long) * @throws SecurityException if the current thread cannot create a thread in the specified thread group */ public JBossThread(final ThreadGroup group, final Runnable target, final String name, final long stackSize) throws SecurityException { super(group, target, name, stackSize); } /** * Interrupt this thread. Logs a trace message and calls the current interrupt handler, if any. The interrupt * handler is called from the calling thread, not the thread being interrupted. */ public void interrupt() { final boolean differentThread = Thread.currentThread() != this; if (differentThread) checkAccess(); // fast check if (isInterrupted()) return; final AtomicInteger stateRef = this.stateRef; int oldVal, newVal; do { oldVal = stateRef.get(); if (oldVal == STATE_INTERRUPT_PENDING || oldVal == STATE_INTERRUPT_IN_PROGRESS) { // already set Messages.msg.tracef("Interrupting thread \"%s\" (already interrupted)", this); return; } else if (oldVal == STATE_INTERRUPT_DEFERRED) { newVal = STATE_INTERRUPT_PENDING; } else { newVal = STATE_INTERRUPT_IN_PROGRESS; } } while (! stateRef.compareAndSet(oldVal, newVal)); if (newVal == STATE_INTERRUPT_IN_PROGRESS) try { doInterrupt(); } finally { // after we return, the thread could be un-interrupted at any time without our knowledge stateRef.set(STATE_MAYBE_INTERRUPTED); if (differentThread) { // unpark the thread if it was waiting to defer interrupts // interrupting the thread will unpark it; it might park after the interrupt though, or wake up before the state is restored LockSupport.unpark(this); } } else { Messages.intMsg.tracef("Interrupting thread \"%s\" (deferred)", this); } } private void doInterrupt() { if (isInterrupted()) return; Messages.msg.tracef("Interrupting thread \"%s\"", this); try { super.interrupt(); } finally { final InterruptHandler interruptHandler = this.interruptHandler; if (interruptHandler != null) { try { interruptHandler.handleInterrupt(this); } catch (Throwable t) { Messages.msg.interruptHandlerThrew(t, interruptHandler); } } } } public boolean isInterrupted() { return this == Thread.currentThread() ? super.isInterrupted() : super.isInterrupted() || (stateRef.get() == STATE_INTERRUPT_PENDING); } /** * Defer interrupts for the duration of some task. Once the task is complete, any deferred interrupt will be * delivered to the thread, thus the thread interrupt status should be checked upon return. If the current thread * is not a {@code JBossThread}, the task is simply run as-is. * * @param task the task to run */ public static void executeWithInterruptDeferred(final Runnable task) { executeWithInterruptDeferred(JBossExecutors.directExecutor(), task); } /** * Defer interrupts for the duration of some task. Once the task is complete, any deferred interrupt will be * delivered to the thread, thus the thread interrupt status should be checked upon return. If the current thread * is not a {@code JBossThread}, the task is simply run as-is. * * @param directExecutor the task executor to use * @param task the task to run */ public static void executeWithInterruptDeferred(final DirectExecutor directExecutor, final Runnable task) { final JBossThread thread = currentThread(); if (registerDeferral(thread)) try { directExecutor.execute(task); } finally { unregisterDeferral(thread); } else { // already deferred directExecutor.execute(task); } } /** * Defer interrupts for the duration of some task. Once the task is complete, any deferred interrupt will be * delivered to the thread, thus the thread interrupt status should be checked upon return. If the current thread * is not a {@code JBossThread}, the task is simply run as-is. * * @param action the task to run * @param the callable's return type * @return the value returned from the callable * @throws Exception if the action throws an exception */ public static T executeWithInterruptDeferred(final Callable action) throws Exception { final JBossThread thread = currentThread(); if (registerDeferral(thread)) try { return action.call(); } finally { unregisterDeferral(thread); } else { // already deferred return action.call(); } } /** * Defer interrupts for the duration of some task. Once the task is complete, any deferred interrupt will be * delivered to the thread, thus the thread interrupt status should be checked upon return. If the current thread * is not a {@code JBossThread}, the task is simply run as-is. * * @param action the task to run * @param the action's return type * @return the value returned from the callable */ public static T executeWithInterruptDeferred(final PrivilegedAction action) { final JBossThread thread = currentThread(); if (registerDeferral(thread)) try { return action.run(); } finally { unregisterDeferral(thread); } else { // already deferred return action.run(); } } /** * Defer interrupts for the duration of some task. Once the task is complete, any deferred interrupt will be * delivered to the thread, thus the thread interrupt status should be checked upon return. If the current thread * is not a {@code JBossThread}, the task is simply run as-is. * * @param action the task to run * @param the action's return type * @return the value returned from the callable * @throws Exception if the action throws an exception */ public static T executeWithInterruptDeferred(final PrivilegedExceptionAction action) throws Exception { final JBossThread thread = currentThread(); if (registerDeferral(thread)) try { return action.run(); } finally { unregisterDeferral(thread); } else { // already deferred return action.run(); } } public static R applyInterruptDeferredEx(final ExceptionBiFunction function, T param1, U param2) throws E { final JBossThread thread = currentThread(); if (registerDeferral(thread)) try { return function.apply(param1, param2); } finally { unregisterDeferral(thread); } else { // already deferred return function.apply(param1, param2); } } public static R applyInterruptDeferredEx(final ExceptionFunction function, T param) throws E { return applyInterruptDeferredEx(Functions.exceptionFunctionBiFunction(), function, param); } public static T getInterruptDeferredEx(final ExceptionSupplier supplier) throws E { return applyInterruptDeferredEx(Functions.exceptionFunctionBiFunction(), Functions.exceptionSupplierFunction(), supplier); } public static void acceptInterruptDeferredEx(final ExceptionObjLongConsumer consumer, T param1, long param2) throws E { final JBossThread thread = currentThread(); if (registerDeferral(thread)) try { consumer.accept(param1, param2); } finally { unregisterDeferral(thread); } else { // already deferred consumer.accept(param1, param2); } } public static void acceptInterruptDeferredEx(final ExceptionObjIntConsumer consumer, T param1, int param2) throws E { final JBossThread thread = currentThread(); if (registerDeferral(thread)) try { consumer.accept(param1, param2); } finally { unregisterDeferral(thread); } else { // already deferred consumer.accept(param1, param2); } } public static void acceptInterruptDeferredEx(final ExceptionBiConsumer consumer, T param1, U param2) throws E { final JBossThread thread = currentThread(); if (registerDeferral(thread)) try { consumer.accept(param1, param2); } finally { unregisterDeferral(thread); } else { // already deferred consumer.accept(param1, param2); } } public static void acceptInterruptDeferredEx(final ExceptionConsumer consumer, T param) throws E { acceptInterruptDeferredEx(Functions.exceptionConsumerBiConsumer(), consumer, param); } public static void runInterruptDeferredEx(final ExceptionRunnable runnable) throws E { acceptInterruptDeferredEx(Functions.exceptionConsumerBiConsumer(), Functions.exceptionRunnableConsumer(), runnable); } public static R applyInterruptResumedEx(final ExceptionBiFunction function, T param1, U param2) throws E { final JBossThread thread = currentThread(); if (unregisterDeferral(thread)) try { return function.apply(param1, param2); } finally { registerDeferral(thread); } else { // already resumed return function.apply(param1, param2); } } public static R applyInterruptResumedEx(final ExceptionFunction function, T param) throws E { return applyInterruptResumedEx(Functions.exceptionFunctionBiFunction(), function, param); } public static T getInterruptResumedEx(final ExceptionSupplier supplier) throws E { return applyInterruptResumedEx(Functions.exceptionFunctionBiFunction(), Functions.exceptionSupplierFunction(), supplier); } public static void acceptInterruptResumedEx(final ExceptionObjLongConsumer consumer, T param1, long param2) throws E { final JBossThread thread = currentThread(); if (unregisterDeferral(thread)) try { consumer.accept(param1, param2); } finally { registerDeferral(thread); } else { // already resumed consumer.accept(param1, param2); } } public static void acceptInterruptResumedEx(final ExceptionObjIntConsumer consumer, T param1, int param2) throws E { final JBossThread thread = currentThread(); if (unregisterDeferral(thread)) try { consumer.accept(param1, param2); } finally { registerDeferral(thread); } else { // already resumed consumer.accept(param1, param2); } } public static void acceptInterruptResumedEx(final ExceptionBiConsumer consumer, T param1, U param2) throws E { final JBossThread thread = currentThread(); if (unregisterDeferral(thread)) try { consumer.accept(param1, param2); } finally { registerDeferral(thread); } else { // already resumed consumer.accept(param1, param2); } } public static void acceptInterruptResumedEx(final ExceptionConsumer consumer, T param) throws E { acceptInterruptResumedEx(Functions.exceptionConsumerBiConsumer(), consumer, param); } public static void runInterruptResumedEx(final ExceptionRunnable runnable) throws E { acceptInterruptResumedEx(Functions.exceptionConsumerBiConsumer(), Functions.exceptionRunnableConsumer(), runnable); } private static boolean unregisterDeferral(final JBossThread thread) { if (thread == null) { return false; } int oldVal, newVal; final AtomicInteger stateRef = thread.stateRef; do { oldVal = stateRef.get(); if (oldVal == STATE_MAYBE_INTERRUPTED || oldVal == STATE_INTERRUPT_IN_PROGRESS) { // already not deferred return false; } else if (oldVal == STATE_INTERRUPT_DEFERRED) { newVal = STATE_MAYBE_INTERRUPTED; } else if (oldVal == STATE_INTERRUPT_PENDING) { newVal = STATE_INTERRUPT_IN_PROGRESS; } else { throw Assert.unreachableCode(); } } while (! stateRef.compareAndSet(oldVal, newVal)); if (newVal == STATE_INTERRUPT_IN_PROGRESS) try { thread.doInterrupt(); } finally { stateRef.set(STATE_MAYBE_INTERRUPTED); } return true; } private static boolean registerDeferral(final JBossThread thread) { if (thread == null) { return false; } final AtomicInteger stateRef = thread.stateRef; int oldVal, newVal; do { oldVal = stateRef.get(); while (oldVal == STATE_INTERRUPT_IN_PROGRESS) { LockSupport.park(); oldVal = stateRef.get(); } if (oldVal == STATE_MAYBE_INTERRUPTED) { newVal = Thread.interrupted() ? STATE_INTERRUPT_DEFERRED : STATE_INTERRUPT_PENDING; } else if (oldVal == STATE_INTERRUPT_DEFERRED || oldVal == STATE_INTERRUPT_PENDING) { // already deferred return false; } else { throw Assert.unreachableCode(); } } while (! stateRef.compareAndSet(oldVal, newVal)); if (newVal == STATE_INTERRUPT_DEFERRED && Thread.interrupted()) { // in case we got interrupted right after we checked interrupt state but before we CAS'd the value. stateRef.set(STATE_INTERRUPT_PENDING); } return true; } /** * Execute the thread's {@code Runnable}. Logs a trace message at the start and end of execution. */ public void run() { Messages.msg.tracef("Thread \"%s\" starting execution", this); try { super.run(); } finally { Messages.msg.tracef("Thread \"%s\" exiting", this); } } /** * Get the current {@code JBossThread}, or {@code null} if the current thread is not a {@code JBossThread}. * * @return the current thread, or {@code null} */ public static JBossThread currentThread() { final Thread thread = Thread.currentThread(); return thread instanceof JBossThread ? (JBossThread) thread : null; } /** * Start the thread. * * @throws IllegalThreadStateException if the thread was already started. */ public void start() { super.start(); Messages.msg.tracef("Started thread \"%s\"", this); } /** * Change the uncaught exception handler for this thread. * * @param eh the new handler */ public void setUncaughtExceptionHandler(final UncaughtExceptionHandler eh) { super.setUncaughtExceptionHandler(eh); Messages.msg.tracef("Changed uncaught exception handler for \"%s\" to %s", this, eh); } /** * Swap the current thread's active interrupt handler. Most callers should restore the old handler in a {@code finally} * block like this: *
     * InterruptHandler oldHandler = JBossThread.getAndSetInterruptHandler(newHandler);
     * try {
     *     ...execute interrupt-sensitive operation...
     * } finally {
     *     JBossThread.getAndSetInterruptHandler(oldHandler);
     * }
     * 
* * @param newInterruptHandler the new interrupt handler * @return the old interrupt handler */ public static InterruptHandler getAndSetInterruptHandler(final InterruptHandler newInterruptHandler) { final JBossThread thread = currentThread(); if (thread == null) { throw Messages.msg.noInterruptHandlers(); } try { return thread.interruptHandler; } finally { thread.interruptHandler = newInterruptHandler; } } public static R applyWithInterruptHandler(InterruptHandler interruptHandler, ExceptionBiFunction function, T param1, U param2) throws E { final JBossThread thread = currentThread(); if (thread == null) { return function.apply(param1, param2); } else { final InterruptHandler old = thread.interruptHandler; thread.interruptHandler = interruptHandler; try { return function.apply(param1, param2); } finally { thread.interruptHandler = old; } } } public static R applyWithInterruptHandler(InterruptHandler interruptHandler, ExceptionFunction function, T param1) throws E { return applyWithInterruptHandler(interruptHandler, Functions.exceptionFunctionBiFunction(), function, param1); } public static R getWithInterruptHandler(InterruptHandler interruptHandler, ExceptionSupplier function) throws E { return applyWithInterruptHandler(interruptHandler, Functions.exceptionFunctionBiFunction(), Functions.exceptionSupplierFunction(), function); } public static void acceptWithInterruptHandler(InterruptHandler interruptHandler, ExceptionObjLongConsumer function, T param1, long param2) throws E { final JBossThread thread = currentThread(); if (thread == null) { function.accept(param1, param2); return; } else { final InterruptHandler old = thread.interruptHandler; thread.interruptHandler = interruptHandler; try { function.accept(param1, param2); return; } finally { thread.interruptHandler = old; } } } public static void acceptWithInterruptHandler(InterruptHandler interruptHandler, ExceptionObjIntConsumer function, T param1, int param2) throws E { final JBossThread thread = currentThread(); if (thread == null) { function.accept(param1, param2); return; } else { final InterruptHandler old = thread.interruptHandler; thread.interruptHandler = interruptHandler; try { function.accept(param1, param2); return; } finally { thread.interruptHandler = old; } } } public static void acceptWithInterruptHandler(InterruptHandler interruptHandler, ExceptionBiConsumer function, T param1, U param2) throws E { final JBossThread thread = currentThread(); if (thread == null) { function.accept(param1, param2); return; } else { final InterruptHandler old = thread.interruptHandler; thread.interruptHandler = interruptHandler; try { function.accept(param1, param2); return; } finally { thread.interruptHandler = old; } } } public static void acceptWithInterruptHandler(InterruptHandler interruptHandler, ExceptionConsumer function, T param1) throws E { acceptWithInterruptHandler(interruptHandler, Functions.exceptionConsumerBiConsumer(), function, param1); } public static void runWithInterruptHandler(InterruptHandler interruptHandler, ExceptionRunnable function) throws E { acceptWithInterruptHandler(interruptHandler, Functions.exceptionConsumerBiConsumer(), Functions.exceptionRunnableConsumer(), function); } /** * Get the thread name information. This includes information about the thread's sequence number and so forth. * * @return the thread name info */ ThreadNameInfo getThreadNameInfo() { return threadNameInfo; } /** * Set the thread name information. This includes information about the thread's sequence number and so forth. * * @param threadNameInfo the new thread name info * @throws SecurityException if the calling thread is not allowed to modify this thread */ void setThreadNameInfo(final ThreadNameInfo threadNameInfo) throws SecurityException { checkAccess(); this.threadNameInfo = threadNameInfo; } } jboss-threads-2.3.2.Final/src/main/java/org/jboss/threads/JBossThreadFactory.java000066400000000000000000000124271325274360100276670ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2017 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.threads; import java.security.AccessController; import java.security.PrivilegedAction; import java.security.AccessControlContext; import java.util.concurrent.ThreadFactory; import java.util.concurrent.atomic.AtomicLong; /** * A factory for {@link JBossThread} instances. */ public final class JBossThreadFactory implements ThreadFactory { private final ThreadGroup threadGroup; private final Boolean daemon; private final Integer initialPriority; private final Thread.UncaughtExceptionHandler uncaughtExceptionHandler; private final Long stackSize; private final String namePattern; private final AtomicLong factoryThreadIndexSequence = new AtomicLong(1L); private final long factoryIndex; private final AccessControlContext creatingContext; private static final AtomicLong globalThreadIndexSequence = new AtomicLong(1L); private static final AtomicLong factoryIndexSequence = new AtomicLong(1L); /** * Construct a new instance. The access control context of the calling thread will be the one used to create * new threads if a security manager is installed. * * @param threadGroup the thread group to assign threads to by default (may be {@code null}) * @param daemon whether the created threads should be daemon threads, or {@code null} to use the thread group's setting * @param initialPriority the initial thread priority, or {@code null} to use the thread group's setting * @param namePattern the name pattern string * @param uncaughtExceptionHandler the uncaught exception handler, if any * @param stackSize the JVM-specific stack size, or {@code null} to leave it unspecified */ public JBossThreadFactory(ThreadGroup threadGroup, final Boolean daemon, final Integer initialPriority, String namePattern, final Thread.UncaughtExceptionHandler uncaughtExceptionHandler, final Long stackSize) { if (threadGroup == null) { final SecurityManager sm = System.getSecurityManager(); threadGroup = sm != null ? sm.getThreadGroup() : Thread.currentThread().getThreadGroup(); } this.threadGroup = threadGroup; this.daemon = daemon; this.initialPriority = initialPriority; this.uncaughtExceptionHandler = uncaughtExceptionHandler; this.stackSize = stackSize; factoryIndex = factoryIndexSequence.getAndIncrement(); if (namePattern == null) { namePattern = "pool-%f-thread-%t"; } this.namePattern = namePattern; this.creatingContext = AccessController.getContext(); } /** * @deprecated Use {@link #JBossThreadFactory(ThreadGroup, Boolean, Integer, String, Thread.UncaughtExceptionHandler, Long)} instead. */ public JBossThreadFactory(ThreadGroup threadGroup, final Boolean daemon, final Integer initialPriority, String namePattern, final Thread.UncaughtExceptionHandler uncaughtExceptionHandler, final Long stackSize, final AccessControlContext ignored) { this(threadGroup, daemon, initialPriority, namePattern, uncaughtExceptionHandler, stackSize); } public Thread newThread(final Runnable target) { final AccessControlContext context; if ((context = creatingContext) != null) { return AccessController.doPrivileged(new ThreadCreateAction(target), context); } else { return createThread(target); } } private final class ThreadCreateAction implements PrivilegedAction { private final Runnable target; private ThreadCreateAction(final Runnable target) { this.target = target; } public Thread run() { return createThread(target); } } private Thread createThread(final Runnable target) { final ThreadNameInfo nameInfo = new ThreadNameInfo(globalThreadIndexSequence.getAndIncrement(), factoryThreadIndexSequence.getAndIncrement(), factoryIndex); final JBossThread thread; if (stackSize != null) { thread = new JBossThread(threadGroup, target, "", stackSize.longValue()); } else { thread = new JBossThread(threadGroup, target); } thread.setThreadNameInfo(nameInfo); thread.setName(nameInfo.format(thread, namePattern)); if (initialPriority != null) thread.setPriority(initialPriority.intValue()); if (daemon != null) thread.setDaemon(daemon.booleanValue()); if (uncaughtExceptionHandler != null) thread.setUncaughtExceptionHandler(uncaughtExceptionHandler); JBossExecutors.clearContextClassLoader(thread); return thread; } } jboss-threads-2.3.2.Final/src/main/java/org/jboss/threads/JBossThreadPoolExecutor.java000066400000000000000000000136331325274360100307100ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2017 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.threads; import java.util.concurrent.RejectedExecutionException; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; import java.util.concurrent.BlockingQueue; import java.util.concurrent.ThreadFactory; import java.util.concurrent.RejectedExecutionHandler; import java.util.concurrent.atomic.AtomicInteger; import org.jboss.threads.management.BoundedQueueThreadPoolExecutorMBean; import org.wildfly.common.Assert; /** * @deprecated Use {@link EnhancedQueueExecutor} instead. */ @Deprecated public final class JBossThreadPoolExecutor extends ThreadPoolExecutor implements BlockingExecutorService, BoundedQueueThreadPoolExecutorMBean, ShutdownListenable { private final SimpleShutdownListenable shutdownListenable = new SimpleShutdownListenable(); private final AtomicInteger rejectCount = new AtomicInteger(); public JBossThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue workQueue) { super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue); setRejectedExecutionHandler(super.getRejectedExecutionHandler()); } public JBossThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue workQueue, ThreadFactory threadFactory) { super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, threadFactory); setRejectedExecutionHandler(super.getRejectedExecutionHandler()); } public JBossThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue workQueue, RejectedExecutionHandler handler) { super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue); setRejectedExecutionHandler(handler); } public JBossThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler) { super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, threadFactory); setRejectedExecutionHandler(handler); } public void execute(final Runnable task) { super.execute(task); } public void executeBlocking(final Runnable task) throws RejectedExecutionException, InterruptedException { super.execute(task); } public void executeBlocking(final Runnable task, final long timeout, final TimeUnit unit) throws RejectedExecutionException, InterruptedException { super.execute(task); } public void executeNonBlocking(final Runnable task) throws RejectedExecutionException { super.execute(task); } public int getLargestThreadCount() { return super.getLargestPoolSize(); } public boolean isAllowCoreThreadTimeout() { return allowsCoreThreadTimeOut(); } public void setAllowCoreThreadTimeout(final boolean allow) { allowCoreThreadTimeOut(allow); } public int getMaxThreads() { return getMaximumPoolSize(); } public void setMaxThreads(final int newSize) { setMaximumPoolSize(newSize); } public int getCoreThreads() { return getCorePoolSize(); } public void setCoreThreads(final int newSize) { setCorePoolSize(newSize); } public long getKeepAliveTime() { return getKeepAliveTime(TimeUnit.MILLISECONDS); } public void setKeepAliveTime(final long milliseconds) { setKeepAliveTime(milliseconds, TimeUnit.MILLISECONDS); } public int getCurrentThreadCount() { return getPoolSize(); } public int getRejectedCount() { return rejectCount.get(); } /** {@inheritDoc} */ public int getQueueSize() { return this.getQueue().size(); } public boolean isBlocking() { return false; } public void setBlocking(final boolean blocking) { throw Assert.unsupported(); } public RejectedExecutionHandler getRejectedExecutionHandler() { return ((CountingRejectHandler)super.getRejectedExecutionHandler()).getDelegate(); } public void setRejectedExecutionHandler(final RejectedExecutionHandler handler) { super.setRejectedExecutionHandler(new CountingRejectHandler(handler)); } /** {@inheritDoc} */ public
void addShutdownListener(final EventListener shutdownListener, final A attachment) { shutdownListenable.addShutdownListener(shutdownListener, attachment); } protected void terminated() { shutdownListenable.shutdown(); } private final class CountingRejectHandler implements RejectedExecutionHandler { private final RejectedExecutionHandler delegate; public CountingRejectHandler(final RejectedExecutionHandler delegate) { this.delegate = delegate; } public RejectedExecutionHandler getDelegate() { return delegate; } public void rejectedExecution(final Runnable r, final ThreadPoolExecutor executor) { rejectCount.incrementAndGet(); if (isShutdown()) { throw Messages.msg.shutDownInitiated(); } delegate.rejectedExecution(r, executor); } } } jboss-threads-2.3.2.Final/src/main/java/org/jboss/threads/LimitedExecutor.java000066400000000000000000000064011325274360100272700ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2017 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.threads; import java.util.ArrayDeque; import java.util.concurrent.Executor; import java.util.concurrent.RejectedExecutionException; import org.wildfly.common.Assert; /** * An executor for long-running tasks which limits the total concurrency over a delegate thread pool. * * @author David M. Lloyd */ public class LimitedExecutor implements Executor { private final Executor executor; private final Thread.UncaughtExceptionHandler handler; private final int concurrencyLimit; private final Runner runner; public LimitedExecutor(final Executor executor, final Thread.UncaughtExceptionHandler handler, final int concurrencyLimit) { this.executor = executor; this.handler = handler; this.concurrencyLimit = concurrencyLimit; this.runner = new Runner(); } public LimitedExecutor(final Executor executor, final int concurrencyLimit) { this(executor, null, concurrencyLimit); } public void execute(final Runnable command) throws RejectedExecutionException { Assert.checkNotNullParam("command", command); runner.add(command); } @SuppressWarnings("serial") class Runner extends ArrayDeque implements Runnable { private int runCount; public synchronized boolean add(final Runnable runnable) { int runCount = this.runCount; if (runCount < concurrencyLimit) { executor.execute(this); this.runCount = runCount + 1; } return super.add(runnable); } public void run() { Runnable task; for (;;) { synchronized (this) { task = poll(); if (task == null) { runCount--; return; } } try { task.run(); } catch (Throwable t) { final Thread.UncaughtExceptionHandler handler = LimitedExecutor.this.handler; if (handler != null) try { handler.uncaughtException(Thread.currentThread(), t); } catch (Throwable ignored) {} } } } public String toString() { return String.format("Task runner for %s", LimitedExecutor.this); } } public String toString() { return String.format("Limited executor (%d tasks) over %s", Integer.valueOf(concurrencyLimit), executor); } } jboss-threads-2.3.2.Final/src/main/java/org/jboss/threads/LoggingUncaughtExceptionHandler.java000066400000000000000000000023551325274360100324300ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2017 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.threads; import org.jboss.logging.Logger; class LoggingUncaughtExceptionHandler implements Thread.UncaughtExceptionHandler { private final Logger log; LoggingUncaughtExceptionHandler(final Logger log) { this.log = log; } public void uncaughtException(final Thread thread, final Throwable throwable) { log.errorf(throwable, "Thread %s threw an uncaught exception", thread); } public String toString() { return String.format("%s to \"%s\"", super.toString(), log.getName()); } } jboss-threads-2.3.2.Final/src/main/java/org/jboss/threads/ManagedThreadPoolExecutor.java000066400000000000000000000167161325274360100312310ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2017 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.threads; import java.util.concurrent.BlockingQueue; import java.util.concurrent.Executor; import java.util.concurrent.RejectedExecutionHandler; import java.util.concurrent.ThreadFactory; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; import org.jboss.threads.management.ManageableThreadPoolExecutorService; import org.jboss.threads.management.StandardThreadPoolMXBean; import org.wildfly.common.Assert; /** * A version of {@link ThreadPoolExecutor} which implements {@link ManageableThreadPoolExecutorService} in order to allow * opting out of using {@link EnhancedQueueExecutor}. */ public final class ManagedThreadPoolExecutor extends ThreadPoolExecutor implements ManageableThreadPoolExecutorService { private final Runnable terminationTask; private final StandardThreadPoolMXBean mxBean = new MXBeanImpl(); private volatile Executor handoffExecutor = JBossExecutors.rejectingExecutor(); private static final RejectedExecutionHandler HANDLER = new RejectedExecutionHandler() { public void rejectedExecution(final Runnable r, final ThreadPoolExecutor executor) { ((ManagedThreadPoolExecutor) executor).reject(r); } }; public ManagedThreadPoolExecutor(final int corePoolSize, final int maximumPoolSize, final long keepAliveTime, final TimeUnit unit, final BlockingQueue workQueue, final Runnable terminationTask) { super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, HANDLER); this.terminationTask = terminationTask; } public ManagedThreadPoolExecutor(final int corePoolSize, final int maximumPoolSize, final long keepAliveTime, final TimeUnit unit, final BlockingQueue workQueue, final ThreadFactory threadFactory, final Runnable terminationTask) { super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, threadFactory, HANDLER); this.terminationTask = terminationTask; } public ManagedThreadPoolExecutor(final int corePoolSize, final int maximumPoolSize, final long keepAliveTime, final TimeUnit unit, final BlockingQueue workQueue, final Executor handoffExecutor, final Runnable terminationTask) { super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, HANDLER); this.terminationTask = terminationTask; this.handoffExecutor = handoffExecutor; } public ManagedThreadPoolExecutor(final int corePoolSize, final int maximumPoolSize, final long keepAliveTime, final TimeUnit unit, final BlockingQueue workQueue, final ThreadFactory threadFactory, final Executor handoffExecutor, final Runnable terminationTask) { super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, threadFactory, HANDLER); this.terminationTask = terminationTask; this.handoffExecutor = handoffExecutor; } public StandardThreadPoolMXBean getThreadPoolMXBean() { return mxBean; } public Executor getHandoffExecutor() { return handoffExecutor; } public void setHandoffExecutor(final Executor handoffExecutor) { Assert.checkNotNullParam("handoffExecutor", handoffExecutor); this.handoffExecutor = handoffExecutor; super.setRejectedExecutionHandler(HANDLER); } void reject(Runnable r) { handoffExecutor.execute(r); } protected void terminated() { terminationTask.run(); } class MXBeanImpl implements StandardThreadPoolMXBean { public float getGrowthResistance() { return 1.0f; } public void setGrowthResistance(final float value) { // ignored } public boolean isGrowthResistanceSupported() { return false; } public int getCorePoolSize() { return ManagedThreadPoolExecutor.this.getCorePoolSize(); } public void setCorePoolSize(final int corePoolSize) { ManagedThreadPoolExecutor.this.setCorePoolSize(corePoolSize); } public boolean isCorePoolSizeSupported() { return true; } public boolean prestartCoreThread() { return ManagedThreadPoolExecutor.this.prestartCoreThread(); } public int prestartAllCoreThreads() { return ManagedThreadPoolExecutor.this.prestartAllCoreThreads(); } public boolean isCoreThreadPrestartSupported() { return true; } public int getMaximumPoolSize() { return ManagedThreadPoolExecutor.this.getMaximumPoolSize(); } public void setMaximumPoolSize(final int maxPoolSize) { ManagedThreadPoolExecutor.this.setMaximumPoolSize(maxPoolSize); } public int getPoolSize() { return ManagedThreadPoolExecutor.this.getPoolSize(); } public int getLargestPoolSize() { return ManagedThreadPoolExecutor.this.getLargestPoolSize(); } public int getActiveCount() { return ManagedThreadPoolExecutor.this.getActiveCount(); } public boolean isAllowCoreThreadTimeOut() { return ManagedThreadPoolExecutor.this.allowsCoreThreadTimeOut(); } public void setAllowCoreThreadTimeOut(final boolean value) { ManagedThreadPoolExecutor.this.allowCoreThreadTimeOut(value); } public long getKeepAliveTimeSeconds() { return ManagedThreadPoolExecutor.this.getKeepAliveTime(TimeUnit.SECONDS); } public void setKeepAliveTimeSeconds(final long seconds) { ManagedThreadPoolExecutor.this.setKeepAliveTime(seconds, TimeUnit.SECONDS); } public int getMaximumQueueSize() { return 0; } public void setMaximumQueueSize(final int size) { } public int getQueueSize() { return ManagedThreadPoolExecutor.this.getQueue().size(); } public int getLargestQueueSize() { return 0; } public boolean isQueueBounded() { return false; } public boolean isQueueSizeModifiable() { return false; } public boolean isShutdown() { return ManagedThreadPoolExecutor.this.isShutdown(); } public boolean isTerminating() { return ManagedThreadPoolExecutor.this.isTerminating(); } public boolean isTerminated() { return ManagedThreadPoolExecutor.this.isTerminated(); } public long getSubmittedTaskCount() { return ManagedThreadPoolExecutor.this.getTaskCount(); } public long getRejectedTaskCount() { return 0; } public long getCompletedTaskCount() { return ManagedThreadPoolExecutor.this.getCompletedTaskCount(); } } } jboss-threads-2.3.2.Final/src/main/java/org/jboss/threads/Messages.java000066400000000000000000000123621325274360100257340ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2017, Red Hat, Inc., 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.ConcurrentModificationException; import java.util.NoSuchElementException; import java.util.concurrent.CancellationException; import java.util.concurrent.ExecutionException; import java.util.concurrent.RejectedExecutionException; import java.util.concurrent.TimeoutException; import org.jboss.logging.BasicLogger; import org.jboss.logging.Logger; import org.jboss.logging.annotations.Cause; import org.jboss.logging.annotations.LogMessage; import org.jboss.logging.annotations.Message; import org.jboss.logging.annotations.MessageLogger; /** * @author David M. Lloyd */ @MessageLogger(projectCode = "JBTHR", length = 5) interface Messages extends BasicLogger { Messages msg = Logger.getMessageLogger(Messages.class, "org.jboss.threads"); Messages intMsg = Logger.getMessageLogger(Messages.class, "org.jboss.threads.interrupt-handler"); // version @Message(value = "JBoss Threads version %s") @LogMessage(level = Logger.Level.INFO) void version(String version); // execution @Message(id = 1, value = "Thread factory did not produce a thread") ThreadCreationException noThreadCreated(); @Message(id = 2, value = "Task limit reached") RejectedExecutionException taskLimitReached(); @Message(id = 3, value = "Operation timed out") TimeoutException operationTimedOut(); @Message(id = 4, value = "Operation was cancelled") CancellationException operationCancelled(); @Message(id = 5, value = "Operation failed") ExecutionException operationFailed(@Cause Throwable cause); @Message(id = 6, value = "Unable to add new thread to the running set") ThreadCreationException cannotAddThread(); @Message(id = 7, value = "Task execution interrupted") @Deprecated ExecutionInterruptedException executionInterrupted(); @Message(id = 8, value = "Task rejected") RejectedExecutionException executionRejected(); @Message(id = 9, value = "Executor has been shut down") StoppedExecutorException shutDownInitiated(); @Message(id = 10, value = "Task execution timed out") @Deprecated ExecutionTimedOutException executionTimedOut(); @Message(id = 11, value = "Task execution failed for task %s") @LogMessage(level = Logger.Level.ERROR) void executionFailed(@Cause Throwable cause, Runnable task); @Message(id = 12, value = "Cannot await termination of a thread pool from one of its own threads") IllegalStateException cannotAwaitWithin(); @Message(id = 13, value = "No executors available to run task") RejectedExecutionException noExecutorsAvailable(); @Message(id = 14, value = "Error submitting task %s to executor") @LogMessage(level = Logger.Level.ERROR) void taskSubmitFailed(@Cause RejectedExecutionException e, Runnable task); // validation @Message(id = 100, value = "Keep-alive may only be set to 0 for this executor type") IllegalArgumentException keepAliveNotZero(); @Message(id = 101, value = "Cannot reduce maximum threads below current thread number of running threads") IllegalArgumentException cannotReduceMaxBelowCurrent(); @Message(id = 102, value = "Empty array parameter is not empty") IllegalArgumentException arrayNotEmpty(); @Message(id = 103, value = "The current thread does not support interrupt handlers") IllegalStateException noInterruptHandlers(); @Message(id = 104, value = "Executor is not shut down") @Deprecated IllegalStateException notShutDown(); @Message(id = 105, value = "Concurrent modification of collection detected") ConcurrentModificationException concurrentModification(); @Message(id = 106, value = "No such element (iteration past end)") NoSuchElementException noSuchElement(); @Message(id = 107, value = "Unknown throwable received") RuntimeException unknownThrowable(@Cause Throwable t); @Message(id = 108, value = "Interrupt handler %s threw an exception") @LogMessage(level = Logger.Level.ERROR) void interruptHandlerThrew(@Cause Throwable cause, InterruptHandler interruptHandler); // security @Message(id = 200, value = "%s() not allowed on container-managed executor") SecurityException notAllowedContainerManaged(String methodName); } jboss-threads-2.3.2.Final/src/main/java/org/jboss/threads/NotifyingDirectExecutor.java000066400000000000000000000024151325274360100310030ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2017 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.threads; class NotifyingDirectExecutor extends DelegatingDirectExecutor implements DirectExecutor { private final TaskNotifier notifier; private final A attachment; NotifyingDirectExecutor(final DirectExecutor delegate, final TaskNotifier notifier, final A attachment) { super(delegate); this.notifier = notifier; this.attachment = attachment; } public void execute(final Runnable command) { JBossExecutors.run(command, getDelegate(), notifier, attachment); } } jboss-threads-2.3.2.Final/src/main/java/org/jboss/threads/NotifyingRunnable.java000066400000000000000000000025211325274360100276160ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2017 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.threads; class NotifyingRunnable extends DelegatingRunnable implements Runnable { private final TaskNotifier notifier; private final A attachment; NotifyingRunnable(final R delegate, final TaskNotifier notifier, final A attachment) { super(delegate); this.notifier = notifier; this.attachment = attachment; } @SuppressWarnings({ "unchecked" }) protected R getDelegate() { return (R) super.getDelegate(); } public void run() { JBossExecutors.run(getDelegate(), notifier, attachment); } } jboss-threads-2.3.2.Final/src/main/java/org/jboss/threads/NullRunnable.java000066400000000000000000000017601325274360100265660ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2017 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.threads; final class NullRunnable implements Runnable { private static final NullRunnable INSTANCE = new NullRunnable(); static NullRunnable getInstance() { return INSTANCE; } NullRunnable() { } public void run() { // do nothing } } jboss-threads-2.3.2.Final/src/main/java/org/jboss/threads/OrderedExecutor.java000066400000000000000000000254501325274360100272720ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2017 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.threads; import java.util.ArrayDeque; import java.util.List; import java.util.Queue; import java.util.concurrent.AbstractExecutorService; import java.util.concurrent.Executor; 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; import org.wildfly.common.Assert; /** * An executor that always runs all tasks in queue order, using a delegate executor to run the tasks. *

* More specifically, if a FIFO queue type is used, any call B to the {@link #execute(Runnable)} method that * happens-after another call A to the same method, will result in B's task running after A's. */ public final class OrderedExecutor extends AbstractExecutorService implements BlockingExecutorService { private final Executor parent; private final Runnable runner = new Runner(); private final Lock lock = new ReentrantLock(); private final Condition removeCondition = lock.newCondition(); // @protectedby lock private final Queue queue; // @protectedby lock private boolean running; // @protectedby lock private boolean blocking; // @protectedby lock private Executor handoffExecutor; /** * Construct a new instance using an unbounded FIFO queue. Since the queue is unbounded, tasks are never * rejected. * * @param parent the parent to delegate tasks to */ public OrderedExecutor(final Executor parent) { this(parent, new ArrayDeque()); } /** * Construct a new instance using the given queue and a blocking reject policy. * * @param parent the parent to delegate tasks to * @param queue the queue to use to hold tasks */ public OrderedExecutor(final Executor parent, final Queue queue) { this(parent, queue, true, null); } /** * Construct a new instance using a bounded FIFO queue of the given size and a blocking reject policy. * * @param parent the parent to delegate tasks to * @param queueLength the fixed length of the queue to use to hold tasks */ public OrderedExecutor(final Executor parent, final int queueLength) { this(parent, new ArrayQueue(queueLength), true, null); } /** * Construct a new instance using a bounded FIFO queue of the given size and a handoff reject policy. * * @param parent the parent executor * @param queueLength the fixed length of the queue to use to hold tasks * @param handoffExecutor the executor to hand tasks to if the queue is full */ public OrderedExecutor(final Executor parent, final int queueLength, final Executor handoffExecutor) { this(parent, new ArrayQueue(queueLength), false, handoffExecutor); } /** * Construct a new instance. * * @param parent the parent executor * @param queue the task queue to use * @param blocking {@code true} if rejected tasks should block, {@code false} if rejected tasks should be handed off * @param handoffExecutor the executor to hand tasks to if the queue is full */ public OrderedExecutor(final Executor parent, final Queue queue, final boolean blocking, final Executor handoffExecutor) { Assert.checkNotNullParam("parent", parent); Assert.checkNotNullParam("queue", queue); this.queue = queue; this.parent = parent; this.blocking = blocking; this.handoffExecutor = handoffExecutor; } /** * Construct a new instance using a bounded FIFO queue of the given size and a handoff reject policy. * * @param parent the parent executor * @param queueLength the fixed length of the queue to use to hold tasks * @param blocking {@code true} if rejected tasks should block, {@code false} if rejected tasks should be handed off * @param handoffExecutor the executor to hand tasks to if the queue is full */ public OrderedExecutor(final Executor parent, final int queueLength, final boolean blocking, final Executor handoffExecutor) { this(parent, new ArrayQueue(queueLength), blocking, handoffExecutor); } /** * Run a task. * * @param task the task to run. */ public void execute(Runnable task) { Assert.checkNotNullParam("task", task); Executor executor; OUT: for (;;) { lock.lock(); try { if (! running) { running = true; boolean ok = false; try { parent.execute(runner); ok = true; } finally { if (! ok) { running = false; } } } if (! queue.offer(task)) { if (blocking) { try { removeCondition.await(); continue; } catch (InterruptedException e) { Thread.currentThread().interrupt(); throw Messages.msg.executionInterrupted(); } } else { executor = handoffExecutor; break; } } return; } finally { lock.unlock(); } } if (executor != null) { executor.execute(task); } } @Deprecated public void executeBlocking(final Runnable task) throws RejectedExecutionException, InterruptedException { Assert.checkNotNullParam("task", task); OUT: for (;;) { lock.lock(); try { if (! running) { running = true; boolean ok = false; try { parent.execute(runner); ok = true; } finally { if (! ok) { running = false; } } } if (! queue.offer(task)) { removeCondition.await(); continue; } return; } finally { lock.unlock(); } } } @Deprecated public void executeBlocking(final Runnable task, final long timeout, final TimeUnit unit) throws RejectedExecutionException, InterruptedException { Assert.checkNotNullParam("task", task); long now = System.currentTimeMillis(); final long deadline = now + unit.toMillis(timeout); if (deadline < 0L) { executeBlocking(task); return; } OUT: for (;;) { lock.lock(); try { if (! running) { running = true; boolean ok = false; try { parent.execute(runner); ok = true; } finally { if (! ok) { running = false; } } } if (! queue.offer(task)) { final long remaining = deadline - now; if (remaining <= 0L) { throw Messages.msg.executionTimedOut(); } removeCondition.await(remaining, TimeUnit.MILLISECONDS); now = System.currentTimeMillis(); continue; } return; } finally { lock.unlock(); } } } @Deprecated public void executeNonBlocking(final Runnable task) throws RejectedExecutionException { Assert.checkNotNullParam("task", task); Executor executor; OUT: for (;;) { lock.lock(); try { if (! running) { running = true; boolean ok = false; try { parent.execute(runner); ok = true; } finally { if (! ok) { running = false; } } } if (! queue.offer(task)) { executor = handoffExecutor; break; } return; } finally { lock.unlock(); } } if (executor != null) { executor.execute(task); } } public boolean isShutdown() { // container managed executors are never shut down from the application's perspective return false; } public boolean isTerminated() { // container managed executors are never shut down from the application's perspective return false; } public boolean awaitTermination(final long timeout, final TimeUnit unit) throws InterruptedException { return false; } public void shutdown() { throw Messages.msg.notAllowedContainerManaged("shutdown"); } public List shutdownNow() { throw Messages.msg.notAllowedContainerManaged("shutdownNow"); } private class Runner implements Runnable { public void run() { for (;;) { final Runnable task; lock.lock(); try { task = queue.poll(); removeCondition.signal(); if (task == null) { running = false; return; } } finally { lock.unlock(); } try { task.run(); } catch (Throwable t) { // todo log? } } } } } jboss-threads-2.3.2.Final/src/main/java/org/jboss/threads/PrivilegedExecutor.java000066400000000000000000000027271325274360100300020ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2017 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ 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) { this.delegate = delegate; this.context = AccessController.getContext(); } public void execute(final Runnable command) { AccessController.doPrivileged((PrivilegedAction) () -> { delegate.execute(command); return null; }, context); } public String toString() { return String.format("%s (for %s) -> %s", super.toString(), context, delegate); } } jboss-threads-2.3.2.Final/src/main/java/org/jboss/threads/QueueExecutor.java000066400000000000000000000747351325274360100270040ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2017 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.threads; import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Queue; import java.util.Set; import java.util.concurrent.AbstractExecutorService; import java.util.concurrent.Executor; import java.util.concurrent.RejectedExecutionException; import java.util.concurrent.ThreadFactory; import java.util.concurrent.TimeUnit; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; import org.jboss.threads.management.BoundedQueueThreadPoolExecutorMBean; import org.wildfly.common.Assert; /** * An executor which uses a regular queue to hold tasks. The executor may be tuned at runtime in many ways. * * @deprecated Use {@link EnhancedQueueExecutor} instead. */ @Deprecated public final class QueueExecutor extends AbstractExecutorService implements BlockingExecutorService, BoundedQueueThreadPoolExecutorMBean, ShutdownListenable { private final SimpleShutdownListenable shutdownListenable = new SimpleShutdownListenable(); private final Lock lock = new ReentrantLock(); // signal when a task is written to the queue private final Condition enqueueCondition = lock.newCondition(); // signal when the queue is read private final Condition removeCondition = lock.newCondition(); // signalled when threads terminate private final Condition threadExitCondition = lock.newCondition(); private final ThreadFactory threadFactory; private final DirectExecutor taskExecutor; // all protected by poolLock... private int coreThreads; private int maxThreads; private int largestPoolSize; private int rejectCount; private boolean allowCoreThreadTimeout; private long keepAliveTime; private TimeUnit keepAliveTimeUnit; private boolean blocking; private Executor handoffExecutor; private int threadCount; private Set workers = new HashSet(); private boolean stop; private Queue queue; /** * Create a new instance. * * @param coreThreads the number of threads to create before enqueueing tasks * @param maxThreads the maximum number of threads to create * @param keepAliveTime the amount of time that an idle thread should remain active * @param keepAliveTimeUnit the unit of time for {@code keepAliveTime} * @param queue the queue to use for tasks * @param threadFactory the thread factory to use for new threads * @param blocking {@code true} if the executor should block when the queue is full and no threads are available, {@code false} to use the handoff executor * @param handoffExecutor the executor which is called when blocking is disabled and a task cannot be accepted, or {@code null} to reject the task * @param taskExecutor the executor to use to execute tasks */ public QueueExecutor(final int coreThreads, final int maxThreads, final long keepAliveTime, final TimeUnit keepAliveTimeUnit, final Queue queue, final ThreadFactory threadFactory, final boolean blocking, final Executor handoffExecutor, final DirectExecutor taskExecutor) { Assert.checkNotNullParam("threadFactory", threadFactory); Assert.checkNotNullParam("queue", queue); Assert.checkNotNullParam("keepAliveTimeUnit", keepAliveTimeUnit); final Lock lock = this.lock; lock.lock(); try { this.threadFactory = threadFactory; // configurable... this.keepAliveTime = keepAliveTime; this.keepAliveTimeUnit = keepAliveTimeUnit; this.coreThreads = coreThreads; this.maxThreads = maxThreads > coreThreads ? maxThreads : coreThreads; this.queue = queue; this.blocking = blocking; this.handoffExecutor = handoffExecutor; this.taskExecutor = taskExecutor; } finally { lock.unlock(); } } /** * Create a new instance. * * @param coreThreads the number of threads to create before enqueueing tasks * @param maxThreads the maximum number of threads to create * @param keepAliveTime the amount of time that an idle thread should remain active * @param keepAliveTimeUnit the unit of time for {@code keepAliveTime} * @param queue the queue to use for tasks * @param threadFactory the thread factory to use for new threads * @param blocking {@code true} if the executor should block when the queue is full and no threads are available, {@code false} to use the handoff executor * @param handoffExecutor the executor which is called when blocking is disabled and a task cannot be accepted, or {@code null} to reject the task */ public QueueExecutor(final int coreThreads, final int maxThreads, final long keepAliveTime, final TimeUnit keepAliveTimeUnit, final Queue queue, final ThreadFactory threadFactory, final boolean blocking, final Executor handoffExecutor) { this(coreThreads, maxThreads, keepAliveTime, keepAliveTimeUnit, queue, threadFactory, blocking, handoffExecutor, JBossExecutors.directExecutor()); } /** * Create a new instance. * * @param coreThreads the number of threads to create before enqueueing tasks * @param maxThreads the maximum number of threads to create * @param keepAliveTime the amount of time that an idle thread should remain active * @param keepAliveTimeUnit the unit of time for {@code keepAliveTime} * @param queueLength the fixed queue length to use for tasks * @param threadFactory the thread factory to use for new threads * @param blocking {@code true} if the executor should block when the queue is full and no threads are available, {@code false} to use the handoff executor * @param handoffExecutor the executor which is called when blocking is disabled and a task cannot be accepted, or {@code null} to reject the task */ public QueueExecutor(final int coreThreads, final int maxThreads, final long keepAliveTime, final TimeUnit keepAliveTimeUnit, final int queueLength, final ThreadFactory threadFactory, final boolean blocking, final Executor handoffExecutor) { this(coreThreads, maxThreads, keepAliveTime, keepAliveTimeUnit, new ArrayQueue(queueLength), threadFactory, blocking, handoffExecutor); } /** * Execute a task. * * @param task the task to execute * @throws RejectedExecutionException when a task is rejected by the handoff executor * @throws StoppedExecutorException when the executor is terminating * @throws ExecutionInterruptedException when blocking is enabled and the current thread is interrupted before a task could be accepted */ public void execute(final Runnable task) throws RejectedExecutionException { Assert.checkNotNullParam("task", task); final Executor executor; final Lock lock = this.lock; lock.lock(); try { for (;;) { if (stop) { throw Messages.msg.shutDownInitiated(); } // Try core thread first, then queue, then extra thread final int count = threadCount; if (count < coreThreads) { startNewThread(task); threadCount = count + 1; return; } // next queue... final Queue queue = this.queue; if (queue.offer(task)) { enqueueCondition.signal(); return; } // extra threads? if (count < maxThreads) { startNewThread(task); threadCount = count + 1; return; } if (blocking) { try { removeCondition.await(); } catch (InterruptedException e) { Thread.currentThread().interrupt(); throw Messages.msg.executionInterrupted(); } } else { // delegate the task outside of the lock. rejectCount++; executor = handoffExecutor; break; } } } finally { lock.unlock(); } if (executor != null) { executor.execute(task); } else { throw Messages.msg.executionRejected(); } return; } /** * Execute a task, blocking until it can be accepted, or until the calling thread is interrupted. * * @param task the task to submit * * @throws org.jboss.threads.StoppedExecutorException if the executor was shut down before the task was accepted * @throws org.jboss.threads.ThreadCreationException if a thread could not be created for some reason * @throws java.util.concurrent.RejectedExecutionException if execution is rejected for some other reason * @throws InterruptedException if the current thread was interrupted before the task could be accepted * @throws NullPointerException if command is {@code null} */ public void executeBlocking(final Runnable task) throws RejectedExecutionException, InterruptedException { Assert.checkNotNullParam("task", task); final Lock lock = this.lock; lock.lock(); try { for (;;) { if (stop) { throw Messages.msg.shutDownInitiated(); } // Try core thread first, then queue, then extra thread final int count = threadCount; if (count < coreThreads) { startNewThread(task); threadCount = count + 1; return; } // next queue... final Queue queue = this.queue; if (queue.offer(task)) { enqueueCondition.signal(); return; } // extra threads? if (count < maxThreads) { startNewThread(task); threadCount = count + 1; return; } removeCondition.await(); } } finally { lock.unlock(); } } /** * Execute a task, blocking until it can be accepted, a timeout elapses, or the calling thread is interrupted. * * @param task the task to submit * @param timeout the amount of time to wait * @param unit the unit of time * * @throws org.jboss.threads.ExecutionTimedOutException if the timeout elapsed before a task could be accepted * @throws org.jboss.threads.StoppedExecutorException if the executor was shut down before the task was accepted * @throws org.jboss.threads.ThreadCreationException if a thread could not be created for some reason * @throws java.util.concurrent.RejectedExecutionException if execution is rejected for some other reason * @throws InterruptedException if the current thread was interrupted before the task could be accepted * @throws NullPointerException if command is {@code null} */ public void executeBlocking(final Runnable task, final long timeout, final TimeUnit unit) throws RejectedExecutionException, InterruptedException { Assert.checkNotNullParam("task", task); long now = System.currentTimeMillis(); final long deadline = now + unit.toMillis(timeout); if (deadline < 0L) { executeBlocking(task); return; } final Lock lock = this.lock; lock.lock(); try { for (;;) { if (stop) { throw Messages.msg.shutDownInitiated(); } // Try core thread first, then queue, then extra thread final int count = threadCount; if (count < coreThreads) { startNewThread(task); threadCount = count + 1; return; } // next queue... final Queue queue = this.queue; if (queue.offer(task)) { enqueueCondition.signal(); return; } // extra threads? if (count < maxThreads) { startNewThread(task); threadCount = count + 1; return; } final long remaining = deadline - now; if (remaining <= 0L) { throw Messages.msg.executionTimedOut(); } removeCondition.await(remaining, TimeUnit.MILLISECONDS); now = System.currentTimeMillis(); } } finally { lock.unlock(); } } /** * Execute a task, without blocking. * * @param task the task to submit * * @throws org.jboss.threads.StoppedExecutorException if the executor was shut down before the task was accepted * @throws org.jboss.threads.ThreadCreationException if a thread could not be created for some reason * @throws java.util.concurrent.RejectedExecutionException if execution is rejected for some other reason * @throws NullPointerException if command is {@code null} */ public void executeNonBlocking(final Runnable task) throws RejectedExecutionException { Assert.checkNotNullParam("task", task); final Executor executor; final Lock lock = this.lock; lock.lock(); try { if (stop) { throw Messages.msg.shutDownInitiated(); } // Try core thread first, then queue, then extra thread final int count = threadCount; if (count < coreThreads) { startNewThread(task); threadCount = count + 1; return; } // next queue... final Queue queue = this.queue; if (queue.offer(task)) { enqueueCondition.signal(); return; } // extra threads? if (count < maxThreads) { startNewThread(task); threadCount = count + 1; return; } // delegate the task outside of the lock. rejectCount++; executor = handoffExecutor; } finally { lock.unlock(); } if (executor != null) { executor.execute(task); } return; } /** {@inheritDoc} */ public void shutdown() { boolean callShutdownListener = false; final Lock lock = this.lock; lock.lock(); try { if (! stop) { stop = true; // wake up the whole town removeCondition.signalAll(); enqueueCondition.signalAll(); if (workers.isEmpty()) { callShutdownListener = true; } else { for (Thread worker : workers) { worker.interrupt(); } } } } finally { lock.unlock(); if (callShutdownListener) shutdownListenable.shutdown(); } } /** {@inheritDoc} */ public List shutdownNow() { boolean callShutdownListener = false; final Lock lock = this.lock; lock.lock(); try { stop = true; removeCondition.signalAll(); enqueueCondition.signalAll(); if (workers.isEmpty()) { callShutdownListener = true; } else { for (Thread worker : workers) { worker.interrupt(); } } final Queue queue = this.queue; final ArrayList list = new ArrayList(queue); queue.clear(); return list; } finally { lock.unlock(); if (callShutdownListener) shutdownListenable.shutdown(); } } /** {@inheritDoc} */ public boolean isShutdown() { final Lock lock = this.lock; lock.lock(); try { return stop; } finally { lock.unlock(); } } /** {@inheritDoc} */ public boolean isTerminated() { final Lock lock = this.lock; lock.lock(); try { return stop && threadCount == 0; } finally { lock.unlock(); } } /** {@inheritDoc} */ public boolean awaitTermination(final long timeout, final TimeUnit unit) throws InterruptedException { final Lock lock = this.lock; lock.lockInterruptibly(); try { if (workers.contains(Thread.currentThread())) { throw Messages.msg.cannotAwaitWithin(); } final long start = System.currentTimeMillis(); long elapsed = 0L; while (! stop && threadCount > 0) { final long remaining = timeout - elapsed; if (remaining <= 0) { return false; } threadExitCondition.await(remaining, unit); elapsed = unit.convert(System.currentTimeMillis() - start, TimeUnit.MILLISECONDS); } return true; } finally { lock.unlock(); } } /** {@inheritDoc} */ public boolean isAllowCoreThreadTimeout() { final Lock lock = this.lock; lock.lock(); try { return allowCoreThreadTimeout; } finally { lock.unlock(); } } /** {@inheritDoc} */ public void setAllowCoreThreadTimeout(boolean allowCoreThreadTimeout) { final Lock lock = this.lock; lock.lock(); try { this.allowCoreThreadTimeout = allowCoreThreadTimeout; if (allowCoreThreadTimeout) { // wake everyone up so core threads can time out enqueueCondition.signalAll(); } } finally { lock.unlock(); } } /** {@inheritDoc} */ public int getCoreThreads() { final Lock lock = this.lock; lock.lock(); try { return coreThreads; } finally { lock.unlock(); } } /** {@inheritDoc} */ public void setCoreThreads(final int coreThreads) { final Lock lock = this.lock; lock.lock(); try { final int oldLimit = this.coreThreads; if (maxThreads < coreThreads) { // don't let the max thread limit be less than the core thread limit. // the called method will signal as needed setMaxThreads(coreThreads); } else if (oldLimit < coreThreads) { // we're growing the number of core threads // therefore signal anyone waiting to add tasks; there might be more threads to add removeCondition.signalAll(); } else if (oldLimit > coreThreads) { // we're shrinking the number of core threads // therefore signal anyone waiting to remove tasks so the pool can shrink properly enqueueCondition.signalAll(); } else { // we aren't changing anything... return; } this.coreThreads = coreThreads; } finally { lock.unlock(); } } /** {@inheritDoc} */ public int getMaxThreads() { final Lock lock = this.lock; lock.lock(); try { return maxThreads; } finally { lock.unlock(); } } /** {@inheritDoc} */ public void setMaxThreads(final int maxThreads) { final Lock lock = this.lock; lock.lock(); try { final int oldLimit = this.maxThreads; if (maxThreads < coreThreads) { // don't let the max thread limit be less than the core thread limit. // the called method will signal as needed setCoreThreads(maxThreads); } else if (oldLimit < maxThreads) { // we're growing the number of extra threads // therefore signal anyone waiting to add tasks; there might be more threads to add removeCondition.signalAll(); } else if (oldLimit > maxThreads) { // we're shrinking the number of extra threads // therefore signal anyone waiting to remove tasks so the pool can shrink properly enqueueCondition.signalAll(); } else { // we aren't changing anything... return; } this.maxThreads = maxThreads; } finally { lock.unlock(); } } /** {@inheritDoc} */ public long getKeepAliveTime() { final Lock lock = this.lock; lock.lock(); try { return keepAliveTime; } finally { lock.unlock(); } } /** * Set the keep-alive time to the given amount of time. * * @param keepAliveTime the amount of time * @param keepAliveTimeUnit the unit of time */ public void setKeepAliveTime(final long keepAliveTime, final TimeUnit keepAliveTimeUnit) { Assert.checkNotNullParam("keepAliveTimeUnit", keepAliveTimeUnit); Assert.checkMinimumParameter("keepAliveTime", 0L, keepAliveTime); final Lock lock = this.lock; lock.lock(); try { this.keepAliveTime = keepAliveTimeUnit.convert(keepAliveTime, TimeUnit.MILLISECONDS); } finally { lock.unlock(); } } /** {@inheritDoc} */ public void setKeepAliveTime(final long milliseconds) { setKeepAliveTime(milliseconds, TimeUnit.MILLISECONDS); } /** * Determine whether this thread pool executor is set to block when a task cannot be accepted immediately. * * @return {@code true} if blocking is enabled, {@code false} if the handoff executor is used */ public boolean isBlocking() { final Lock lock = this.lock; lock.lock(); try { return blocking; } finally { lock.unlock(); } } /** * Set whether this thread pool executor should be set to block when a task cannot be accepted immediately. * * @param blocking {@code true} if blocking is enabled, {@code false} if the handoff executor is used */ public void setBlocking(boolean blocking) { final Lock lock = this.lock; lock.lock(); try { this.blocking = blocking; } finally { lock.unlock(); } } /** * Get the handoff executor which is called when a task cannot be accepted immediately. * * @return the handoff executor */ public Executor getHandoffExecutor() { final Lock lock = this.lock; lock.lock(); try { return handoffExecutor; } finally { lock.unlock(); } } /** * Set the handoff executor which is called when a task cannot be accepted immediately. * * @param handoffExecutor the handoff executor */ public void setHandoffExecutor(final Executor handoffExecutor) { final Lock lock = this.lock; lock.lock(); try { this.handoffExecutor = handoffExecutor; } finally { lock.unlock(); } } /** {@inheritDoc} */ public void addShutdownListener(final EventListener shutdownListener, final A attachment) { shutdownListenable.addShutdownListener(shutdownListener, attachment); } // call with lock held! private void startNewThread(final Runnable task) { final Thread thread = threadFactory.newThread(new Worker(task)); if (thread == null) { throw Messages.msg.noThreadCreated(); } workers.add(thread); final int size = workers.size(); if (size > largestPoolSize) { largestPoolSize = size; } thread.start(); } // call with lock held! private Runnable pollTask() { final Runnable task = queue.poll(); if (task != null) { removeCondition.signal(); return task; } else { if (-- threadCount == 0) { threadExitCondition.signalAll(); } return null; } } // call with lock held! private Runnable takeTask() { final Condition removeCondition = this.removeCondition; Runnable task = queue.poll(); if (task != null) { removeCondition.signal(); return task; } else { final Condition enqueueCondition = this.enqueueCondition; final long start = System.currentTimeMillis(); boolean intr = Thread.interrupted(); try { long elapsed = 0L; for (;;) { // these parameters may change on each iteration final int threadCount = this.threadCount; final int coreThreadLimit = coreThreads; final boolean allowCoreThreadTimeout = this.allowCoreThreadTimeout; if (stop || threadCount > maxThreads) { // too many threads. Handle a task if there is one, otherwise exit return pollTask(); } else if (allowCoreThreadTimeout || threadCount > coreThreadLimit) { final TimeUnit timeUnit = keepAliveTimeUnit; final long time = keepAliveTime; final long remaining = time - timeUnit.convert(elapsed, TimeUnit.MILLISECONDS); if (remaining > 0L) { try { enqueueCondition.await(remaining, timeUnit); } catch (InterruptedException e) { intr = true; } } else { // the timeout has expired return pollTask(); } } else { // ignore timeout until we are not a core thread or until core threads are allowed to time out try { enqueueCondition.await(); } catch (InterruptedException e) { intr = true; } } task = queue.poll(); if (task != null) { removeCondition.signal(); return task; } elapsed = System.currentTimeMillis() - start; } } finally { if (intr) { Thread.currentThread().interrupt(); } } } } /** {@inheritDoc} */ public int getCurrentThreadCount() { final Lock lock = this.lock; lock.lock(); try { return workers.size(); } finally { lock.unlock(); } } /** {@inheritDoc} */ public int getLargestThreadCount() { final Lock lock = this.lock; lock.lock(); try { return largestPoolSize; } finally { lock.unlock(); } } /** {@inheritDoc} */ public int getRejectedCount() { final Lock lock = this.lock; lock.lock(); try { return rejectCount; } finally { lock.unlock(); } } /** {@inheritDoc} */ public int getQueueSize() { return this.queue.size(); } private void runTask(Runnable task) { if (task != null) try { taskExecutor.execute(task); } catch (Throwable t) { Messages.msg.executionFailed(t, task); } } private class Worker implements Runnable { private volatile Runnable first; public Worker(final Runnable command) { first = command; } public void run() { final Lock lock = QueueExecutor.this.lock; try { Runnable task = first; // Release reference to task first = null; runTask(task); for (;;) { // don't hang on to task while we possibly block waiting for the next one task = null; lock.lock(); try { if (stop) { // drain queue if ((task = pollTask()) == null) { return; } Thread.currentThread().interrupt(); } else { // get next task if ((task = takeTask()) == null) { return; } } } finally { lock.unlock(); } runTask(task); Thread.interrupted(); } } finally { boolean last = false; lock.lock(); try { workers.remove(Thread.currentThread()); last = stop && workers.isEmpty(); } finally { lock.unlock(); } if (last) { shutdownListenable.shutdown(); } } } } } jboss-threads-2.3.2.Final/src/main/java/org/jboss/threads/QueuelessExecutor.java000066400000000000000000000567141325274360100276700ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2017 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.threads; import java.util.Collections; import java.util.Date; import java.util.HashSet; import java.util.List; import java.util.Set; import java.util.concurrent.AbstractExecutorService; import java.util.concurrent.Executor; import java.util.concurrent.RejectedExecutionException; import java.util.concurrent.ThreadFactory; import java.util.concurrent.TimeUnit; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; import org.jboss.threads.management.BoundedThreadPoolExecutorMBean; import org.wildfly.common.Assert; /** * 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. * * @deprecated Use {@link EnhancedQueueExecutor} instead. */ @Deprecated public final class QueuelessExecutor extends AbstractExecutorService implements BlockingExecutorService, BoundedThreadPoolExecutorMBean, ShutdownListenable { private final SimpleShutdownListenable shutdownListenable = new SimpleShutdownListenable(); private final ThreadFactory threadFactory; private final DirectExecutor taskExecutor; private final Lock lock = new ReentrantLock(false); private final Condition runnableDequeued = lock.newCondition(); private final Condition nextReady = lock.newCondition(); private final Condition workerDequeued = lock.newCondition(); private final Condition taskEnqueued = lock.newCondition(); private final Condition threadDeath = lock.newCondition(); /** * Protected by {@link #lock} */ private final Set runningThreads = new HashSet(256); /** * Protected by {@link #lock}, signal {@link #runnableDequeued} on clear */ private Runnable workRunnable; /** * Protected by {@link #lock}, signal {@link #workerDequeued} on clear */ private Worker waitingWorker; /** * Configuration value. * Protected by {@link #lock} */ private long keepAliveTime; /** * Configuration value. * Protected by {@link #lock} */ private int maxThreads; /** * Specify whether this executor blocks when no threads are available. * Protected by {@link #lock} */ private boolean blocking; private Executor handoffExecutor; private boolean stop; //-- statistics -- private int largestPoolSize; private int rejectedCount; public QueuelessExecutor(final ThreadFactory threadFactory, final DirectExecutor taskExecutor, final Executor handoffExecutor, final long keepAliveTime) { this.threadFactory = threadFactory; this.taskExecutor = taskExecutor; this.handoffExecutor = handoffExecutor; this.keepAliveTime = keepAliveTime; } public int getMaxThreads() { final Lock lock = this.lock; lock.lock(); try { return maxThreads; } finally { lock.unlock(); } } public void setMaxThreads(final int newSize) { Assert.checkMinimumParameter("newSize", 1, newSize); final Lock lock = this.lock; lock.lock(); try { maxThreads = newSize; } finally { lock.unlock(); } } public long getKeepAliveTime() { final Lock lock = this.lock; lock.lock(); try { return keepAliveTime; } finally { lock.unlock(); } } public void setKeepAliveTime(final long milliseconds) { final Lock lock = this.lock; lock.lock(); try { keepAliveTime = milliseconds; } finally { lock.unlock(); } } public int getCurrentThreadCount() { final Lock lock = this.lock; lock.lock(); try { return runningThreads.size(); } finally { lock.unlock(); } } public int getLargestThreadCount() { final Lock lock = this.lock; lock.lock(); try { return largestPoolSize; } finally { lock.unlock(); } } public int getRejectedCount() { final Lock lock = this.lock; lock.lock(); try { return rejectedCount; } finally { lock.unlock(); } } /** {@inheritDoc} */ public int getQueueSize() { return 0; } public boolean isBlocking() { final Lock lock = this.lock; lock.lock(); try { return blocking; } finally { lock.unlock(); } } public void setBlocking(final boolean blocking) { final Lock lock = this.lock; lock.lock(); try { this.blocking = blocking; } finally { lock.unlock(); } } public Executor getHandoffExecutor() { final Lock lock = this.lock; lock.lock(); try { return handoffExecutor; } finally { lock.unlock(); } } public void setHandoffExecutor(final Executor handoffExecutor) { final Lock lock = this.lock; lock.lock(); try { this.handoffExecutor = handoffExecutor; } finally { lock.unlock(); } } public void shutdown() { boolean callShutdownListener = false; final Lock lock = this.lock; lock.lock(); try { if (! stop) { if (runningThreads.isEmpty()) { callShutdownListener = true; } else { for (Thread runningThread : runningThreads) { runningThread.interrupt(); } } } stop = true; // wake up all waiters runnableDequeued.signalAll(); nextReady.signalAll(); workerDequeued.signalAll(); taskEnqueued.signalAll(); } finally { lock.unlock(); if (callShutdownListener) shutdownListenable.shutdown(); } } public boolean awaitTermination(final long timeout, final TimeUnit unit) throws InterruptedException { final Lock lock = this.lock; lock.lock(); try { if (! stop) { throw Messages.msg.notShutDown(); } final Date deadline = new Date(clipHigh(unit.toMillis(timeout) + System.currentTimeMillis())); final Condition threadDeath = this.threadDeath; while (! runningThreads.isEmpty() && threadDeath.awaitUntil(deadline)); return runningThreads.isEmpty(); } finally { lock.unlock(); } } public List shutdownNow() { shutdown(); // tasks are never queued return Collections.emptyList(); } public boolean isShutdown() { final Lock lock = this.lock; lock.lock(); try { return stop; } finally { lock.unlock(); } } public boolean isTerminated() { final Lock lock = this.lock; lock.lock(); try { return stop && runningThreads.isEmpty(); } finally { lock.unlock(); } } public void execute(final Runnable task) { Assert.checkNotNullParam("task", task); final Executor executor; final Set runningThreads = this.runningThreads; final Condition runnableDequeued = this.runnableDequeued; final Lock lock = this.lock; Runnable workRunnable; lock.lock(); try { for (;;) { if (stop) { throw Messages.msg.shutDownInitiated(); } final Worker waitingWorker; if ((waitingWorker = this.waitingWorker) != null) { // a worker thread was waiting for a task; give it the task and wake it up waitingWorker.setRunnable(task); taskEnqueued.signal(); this.waitingWorker = null; workerDequeued.signal(); return; } // no worker thread was waiting final int currentSize = runningThreads.size(); if (currentSize < maxThreads) { // if we haven't reached the thread limit yet, start up another thread final Thread thread = threadFactory.newThread(new Worker(task)); if (thread == null) { throw Messages.msg.noThreadCreated(); } if (! runningThreads.add(thread)) { throw Messages.msg.cannotAddThread(); } if (currentSize >= largestPoolSize) { largestPoolSize = currentSize + 1; } thread.start(); return; } if (! blocking) { // not blocking, not accepted executor = handoffExecutor; rejectedCount++; // fall out to execute outside of lock break; } workRunnable = this.workRunnable; if (workRunnable != null) { // someone else is waiting for a worker, so we wait for them try { nextReady.await(); continue; } catch (InterruptedException e) { Thread.currentThread().interrupt(); throw Messages.msg.executionInterrupted(); } } this.workRunnable = task; try { runnableDequeued.await(); if (this.workRunnable == null) { // task was accepted nextReady.signal(); return; } } catch (InterruptedException e) { Thread.currentThread().interrupt(); throw Messages.msg.executionInterrupted(); } finally { this.workRunnable = null; } } } finally { lock.unlock(); } if (executor != null) { executor.execute(task); } else { throw Messages.msg.executionRejected(); } } public void executeBlocking(final Runnable task) throws RejectedExecutionException, InterruptedException { Assert.checkNotNullParam("task", task); final Set runningThreads = this.runningThreads; final Condition runnableDequeued = this.runnableDequeued; final Lock lock = this.lock; Runnable workRunnable; lock.lock(); try { for (;;) { if (stop) { throw Messages.msg.shutDownInitiated(); } final Worker waitingWorker; if ((waitingWorker = this.waitingWorker) != null) { // a worker thread was waiting for a task; give it the task and wake it up waitingWorker.setRunnable(task); taskEnqueued.signal(); this.waitingWorker = null; workerDequeued.signal(); return; } // no worker thread was waiting final int currentSize = runningThreads.size(); if (currentSize < maxThreads) { // if we haven't reached the thread limit yet, start up another thread final Thread thread = threadFactory.newThread(new Worker(task)); if (thread == null) { throw Messages.msg.noThreadCreated(); } if (! runningThreads.add(thread)) { throw Messages.msg.cannotAddThread(); } if (currentSize >= largestPoolSize) { largestPoolSize = currentSize + 1; } thread.start(); return; } workRunnable = this.workRunnable; if (workRunnable != null) { // someone else is waiting for a worker, so we wait for them nextReady.await(); continue; } this.workRunnable = task; try { runnableDequeued.await(); if (this.workRunnable == null) { // task was accepted nextReady.signal(); return; } } finally { this.workRunnable = null; } } } finally { lock.unlock(); } } public void executeBlocking(final Runnable task, final long timeout, final TimeUnit unit) throws RejectedExecutionException, InterruptedException { Assert.checkNotNullParam("task", task); Assert.checkNotNullParam("unit", unit); long now = System.currentTimeMillis(); final long deadline = now + unit.toMillis(timeout); if (deadline < 0L) { executeBlocking(task); return; } final Set runningThreads = this.runningThreads; final Condition runnableDequeued = this.runnableDequeued; final Lock lock = this.lock; Runnable workRunnable; lock.lock(); try { for (;;) { if (stop) { throw Messages.msg.shutDownInitiated(); } final Worker waitingWorker; if ((waitingWorker = this.waitingWorker) != null) { // a worker thread was waiting for a task; give it the task and wake it up waitingWorker.setRunnable(task); taskEnqueued.signal(); this.waitingWorker = null; workerDequeued.signal(); return; } // no worker thread was waiting final int currentSize = runningThreads.size(); if (currentSize < maxThreads) { // if we haven't reached the thread limit yet, start up another thread final Thread thread = threadFactory.newThread(new Worker(task)); if (thread == null) { throw Messages.msg.noThreadCreated(); } if (! runningThreads.add(thread)) { throw Messages.msg.cannotAddThread(); } if (currentSize >= largestPoolSize) { largestPoolSize = currentSize + 1; } thread.start(); return; } workRunnable = this.workRunnable; if (workRunnable != null) { // someone else is waiting for a worker, so we wait for them nextReady.await(); continue; } this.workRunnable = task; try { final long remaining = deadline - now; if (remaining <= 0L) { throw Messages.msg.executionTimedOut(); } runnableDequeued.await(remaining, TimeUnit.MILLISECONDS); now = System.currentTimeMillis(); if (this.workRunnable == null) { // task was accepted nextReady.signal(); return; } } finally { this.workRunnable = null; } } } finally { lock.unlock(); } } public void executeNonBlocking(final Runnable task) throws RejectedExecutionException { Assert.checkNotNullParam("task", task); final Executor executor; final Set runningThreads = this.runningThreads; final Lock lock = this.lock; lock.lock(); try { for (;;) { if (stop) { throw Messages.msg.shutDownInitiated(); } final Worker waitingWorker; if ((waitingWorker = this.waitingWorker) != null) { // a worker thread was waiting for a task; give it the task and wake it up waitingWorker.setRunnable(task); taskEnqueued.signal(); this.waitingWorker = null; workerDequeued.signal(); return; } // no worker thread was waiting final int currentSize = runningThreads.size(); if (currentSize < maxThreads) { // if we haven't reached the thread limit yet, start up another thread final Thread thread = threadFactory.newThread(new Worker(task)); if (thread == null) { throw Messages.msg.noThreadCreated(); } if (! runningThreads.add(thread)) { throw Messages.msg.cannotAddThread(); } if (currentSize >= largestPoolSize) { largestPoolSize = currentSize + 1; } thread.start(); return; } // not blocking, not accepted executor = handoffExecutor; rejectedCount++; // fall out to execute outside of lock break; } } finally { lock.unlock(); } if (executor != null) { executor.execute(task); } else { throw Messages.msg.executionRejected(); } } /** {@inheritDoc} */ public void addShutdownListener(final EventListener shutdownListener, final A attachment) { shutdownListenable.addShutdownListener(shutdownListener, attachment); } private static long clipHigh(long value) { return value < 0 ? Long.MAX_VALUE : value; } private final class Worker implements Runnable { private Runnable runnable; private Worker(final Runnable runnable) { this.runnable = runnable; } private void setRunnable(final Runnable runnable) { this.runnable = runnable; } private boolean awaitTimed(Condition condition, long idleSince) { final long end = clipHigh(idleSince + keepAliveTime); long remaining = end - System.currentTimeMillis(); if (remaining < 0L) { return false; } if (stop) return false; try { condition.await(remaining, TimeUnit.MILLISECONDS); } catch (InterruptedException e) { } return ! stop; } public void run() { final Lock lock = QueuelessExecutor.this.lock; final Condition workerDequeued = QueuelessExecutor.this.workerDequeued; final Condition runnableDequeued = QueuelessExecutor.this.runnableDequeued; final Condition taskEnqueued = QueuelessExecutor.this.taskEnqueued; final Set runningThreads = QueuelessExecutor.this.runningThreads; final DirectExecutor taskExecutor = QueuelessExecutor.this.taskExecutor; final Thread thread = Thread.currentThread(); long idleSince = Long.MAX_VALUE; Runnable runnable = this.runnable; boolean last = false; this.runnable = null; try { MAIN: for (;;) { // Run task try { taskExecutor.execute(runnable); } catch (Throwable t) { Messages.msg.executionFailed(t, runnable); } idleSince = System.currentTimeMillis(); // Get next task lock.lock(); try { if (stop || runningThreads.size() > maxThreads) { if (runningThreads.remove(thread) && runningThreads.isEmpty()) { threadDeath.signalAll(); last = true; } return; } if ((runnable = workRunnable) != null) { // there's a task, take it and continue on to the top of the loop workRunnable = null; runnableDequeued.signal(); } else { // no executors are waiting, so we wait instead for an executor while (waitingWorker != null) { // wait... to wait if (! awaitTimed(workerDequeued, idleSince)) return; if ((runnable = workRunnable) != null) { // sniped an easy one by luck! continue MAIN; } } waitingWorker = this; try { do { // wait for a job if (! awaitTimed(taskEnqueued, idleSince)) return; } while ((runnable = this.runnable) == null); this.runnable = null; } finally { if (waitingWorker == this) { waitingWorker = null; workerDequeued.signal(); } } } } finally { lock.unlock(); } } } finally { lock.lock(); try { if (runningThreads.remove(thread) && stop && runningThreads.isEmpty()) { threadDeath.signalAll(); last = true; } } finally { lock.unlock(); } if (last) { shutdownListenable.shutdown(); } } } } } jboss-threads-2.3.2.Final/src/main/java/org/jboss/threads/RejectingExecutor.java000066400000000000000000000024121325274360100276110ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2017 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.threads; import java.util.concurrent.RejectedExecutionException; class RejectingExecutor implements DirectExecutor { static final RejectingExecutor INSTANCE = new RejectingExecutor(); private final String message; private RejectingExecutor() { message = null; } RejectingExecutor(final String message) { this.message = message; } public void execute(final Runnable command) { throw new RejectedExecutionException(message); } public String toString() { return "Rejecting executor"; } } jboss-threads-2.3.2.Final/src/main/java/org/jboss/threads/ShutdownListenable.java000066400000000000000000000024131325274360100277770ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2017 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.threads; /** * An object which can have shutdown listeners registered on it. * * @author David M. Lloyd */ public interface ShutdownListenable { /** * Add a shutdown listener. If the target object is already shut down, the listener is invoked directly. * * @param shutdownListener the listener * @param attachment the attachment value to pass to the listener * @param the attachment type */ void addShutdownListener(EventListener shutdownListener, A attachment); } jboss-threads-2.3.2.Final/src/main/java/org/jboss/threads/SimpleDirectExecutor.java000066400000000000000000000020451325274360100302650ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2017 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.threads; class SimpleDirectExecutor implements DirectExecutor { static final DirectExecutor INSTANCE = new SimpleDirectExecutor(); private SimpleDirectExecutor() { } public void execute(final Runnable command) { command.run(); } public String toString() { return "Direct executor"; } } jboss-threads-2.3.2.Final/src/main/java/org/jboss/threads/SimpleShutdownListenable.java000066400000000000000000000046111325274360100311530ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2017 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.threads; import java.util.ArrayList; import java.util.List; /** * A simple shutdown-listenable registry. * * @author David M. Lloyd */ public final class SimpleShutdownListenable implements ShutdownListenable { private List> list = new ArrayList>(); /** {@inheritDoc} */ public void addShutdownListener(final EventListener shutdownListener, final A attachment) { synchronized (this) { final Registration reg = new Registration(shutdownListener, attachment); if (list == null) { reg.run(); } else { list.add(reg); } } } /** * Run and remove all registered listeners, and mark this object as having been shut down so that * future listeners are invoked immediately. */ public void shutdown() { final List> list; synchronized (this) { list = this.list; this.list = null; } if (list != null) { for (Registration registration : list) { registration.run(); } } } private static final class Registration { private final EventListener listener; private final A attachment; private Registration(final EventListener listener, final A attachment) { this.listener = listener; this.attachment = attachment; } void run() { try { listener.handleEvent(attachment); } catch (Throwable t) { // todo log it } } } } jboss-threads-2.3.2.Final/src/main/java/org/jboss/threads/StoppedExecutorException.java000066400000000000000000000047301325274360100312010ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2017 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.threads; import java.util.concurrent.RejectedExecutionException; /** * Thrown when a task is submitted to an executor which is in the process of, or has completed shutting down. */ public class StoppedExecutorException extends RejectedExecutionException { private static final long serialVersionUID = 4815103522815471074L; /** * Constructs a {@code StoppedExecutorException} with no detail message. The cause is not initialized, and may * subsequently be initialized by a call to {@link #initCause(Throwable) initCause}. */ public StoppedExecutorException() { } /** * Constructs a {@code StoppedExecutorException} with the specified detail message. The cause is not initialized, and * may subsequently be initialized by a call to {@link #initCause(Throwable) initCause}. * * @param msg the detail message */ public StoppedExecutorException(final String msg) { super(msg); } /** * Constructs a {@code StoppedExecutorException} with the specified cause. The detail message is set to: *

(cause == null ? null : cause.toString())
* (which typically contains the class and detail message of {@code cause}). * * @param cause the cause (which is saved for later retrieval by the {@link #getCause()} method) */ public StoppedExecutorException(final Throwable cause) { super(cause); } /** * Constructs a {@code StoppedExecutorException} with the specified detail message and cause. * * @param msg the detail message * @param cause the cause (which is saved for later retrieval by the {@link #getCause()} method) */ public StoppedExecutorException(final String msg, final Throwable cause) { super(msg, cause); } } jboss-threads-2.3.2.Final/src/main/java/org/jboss/threads/TaskNotifier.java000066400000000000000000000027311325274360100265660ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2017 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.threads; /** * A notifier which is called when tasks start, stop, or fail. * * @param the task type * @param the attachment type */ public interface TaskNotifier { /** * A task was started. * * @param runnable the task * @param attachment the attachment */ void started(R runnable, A attachment); /** * A task has failed. * * @param runnable the task * @param reason the reason for the failure * @param attachment the attachment */ void failed(R runnable, Throwable reason, A attachment); /** * A task has completed. * * @param runnable the task * @param attachment the attachment */ void finished(R runnable, A attachment); } jboss-threads-2.3.2.Final/src/main/java/org/jboss/threads/ThreadCreationException.java000066400000000000000000000046601325274360100307420ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2017 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.threads; import java.util.concurrent.RejectedExecutionException; /** * Thrown when a thread factory refuses to create a thread for a thread pool. */ public class ThreadCreationException extends RejectedExecutionException { private static final long serialVersionUID = 5666802385744283783L; /** * Constructs a {@code ThreadCreationException} with no detail message. The cause is not initialized, and may * subsequently be initialized by a call to {@link #initCause(Throwable) initCause}. */ public ThreadCreationException() { } /** * Constructs a {@code ThreadCreationException} with the specified detail message. The cause is not initialized, and may * subsequently be initialized by a call to {@link #initCause(Throwable) initCause}. * * @param msg the detail message */ public ThreadCreationException(final String msg) { super(msg); } /** * Constructs a {@code ThreadCreationException} with the specified cause. The detail message is set to: *
(cause == null ? null : cause.toString())
* (which typically contains the class and detail message of {@code cause}). * * @param cause the cause (which is saved for later retrieval by the {@link #getCause()} method) */ public ThreadCreationException(final Throwable cause) { super(cause); } /** * Constructs a {@code ThreadCreationException} with the specified detail message and cause. * * @param msg the detail message * @param cause the cause (which is saved for later retrieval by the {@link #getCause()} method) */ public ThreadCreationException(final String msg, final Throwable cause) { super(msg, cause); } } jboss-threads-2.3.2.Final/src/main/java/org/jboss/threads/ThreadFactoryExecutor.java000066400000000000000000000233351325274360100304450ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2017 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.threads; import java.util.concurrent.Semaphore; import java.util.concurrent.ThreadFactory; import java.util.concurrent.RejectedExecutionException; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; import org.jboss.threads.management.BoundedThreadPoolExecutorMBean; import org.wildfly.common.Assert; @Deprecated class ThreadFactoryExecutor implements BlockingExecutor, BoundedThreadPoolExecutorMBean { private final ThreadFactory factory; private final Semaphore limitSemaphore; private final DirectExecutor taskExecutor; private final Object lock = new Object(); private int maxThreads; private int largestThreadCount; private int currentThreadCount; private final AtomicInteger rejected = new AtomicInteger(); private volatile boolean blocking; ThreadFactoryExecutor(final ThreadFactory factory, int maxThreads, boolean blocking, final DirectExecutor taskExecutor) { this.factory = factory; this.maxThreads = maxThreads; this.blocking = blocking; this.taskExecutor = taskExecutor; limitSemaphore = new Semaphore(maxThreads); } public int getMaxThreads() { synchronized (lock) { return maxThreads; } } public void setMaxThreads(final int maxThreads) { Assert.checkMinimumParameter("maxThreads", 0, maxThreads); synchronized (lock) { final int old = this.maxThreads; final int diff = old - maxThreads; if (diff < 0) { limitSemaphore.release(-diff); } else if (diff > 0) { if (! limitSemaphore.tryAcquire(diff)) { throw Messages.msg.cannotReduceMaxBelowCurrent(); } } this.maxThreads = maxThreads; } } public void execute(final Runnable task) { Assert.checkNotNullParam("task", task); try { final Semaphore semaphore = limitSemaphore; if (blocking) { try { semaphore.acquire(); } catch (InterruptedException e) { Thread.currentThread().interrupt(); throw Messages.msg.executionInterrupted(); } } else { if (! semaphore.tryAcquire()) { throw Messages.msg.taskLimitReached(); } } boolean ok = false; try { final Thread thread = factory.newThread(new Runnable() { public void run() { try { synchronized (lock) { int t = ++currentThreadCount; if (t > largestThreadCount) { largestThreadCount = t; } } taskExecutor.execute(task); synchronized (lock) { currentThreadCount--; } } finally { limitSemaphore.release(); } } }); if (thread == null) { throw Messages.msg.noThreadCreated(); } thread.start(); ok = true; } finally { if (! ok) semaphore.release(); } } catch (RejectedExecutionException e) { rejected.getAndIncrement(); throw e; } } public void executeBlocking(final Runnable task) throws RejectedExecutionException, InterruptedException { Assert.checkNotNullParam("task", task); try { final Semaphore semaphore = limitSemaphore; semaphore.acquire(); boolean ok = false; try { final Thread thread = factory.newThread(new Runnable() { public void run() { try { synchronized (lock) { int t = ++currentThreadCount; if (t > largestThreadCount) { largestThreadCount = t; } } taskExecutor.execute(task); synchronized (lock) { currentThreadCount--; } } finally { limitSemaphore.release(); } } }); if (thread == null) { throw Messages.msg.noThreadCreated(); } thread.start(); ok = true; } finally { if (! ok) semaphore.release(); } } catch (RejectedExecutionException e) { rejected.getAndIncrement(); throw e; } } public void executeBlocking(final Runnable task, final long timeout, final TimeUnit unit) throws RejectedExecutionException, InterruptedException { Assert.checkNotNullParam("task", task); try { final Semaphore semaphore = limitSemaphore; if (! semaphore.tryAcquire(timeout, unit)) { throw Messages.msg.executionTimedOut(); } boolean ok = false; try { final Thread thread = factory.newThread(new Runnable() { public void run() { try { synchronized (lock) { int t = ++currentThreadCount; if (t > largestThreadCount) { largestThreadCount = t; } } taskExecutor.execute(task); synchronized (lock) { currentThreadCount--; } } finally { limitSemaphore.release(); } } }); if (thread == null) { throw Messages.msg.noThreadCreated(); } thread.start(); ok = true; } finally { if (! ok) semaphore.release(); } } catch (RejectedExecutionException e) { rejected.getAndIncrement(); throw e; } } public void executeNonBlocking(final Runnable task) throws RejectedExecutionException { Assert.checkNotNullParam("task", task); try { final Semaphore semaphore = limitSemaphore; if (! semaphore.tryAcquire()) { throw Messages.msg.taskLimitReached(); } boolean ok = false; try { final Thread thread = factory.newThread(new Runnable() { public void run() { try { synchronized (lock) { int t = ++currentThreadCount; if (t > largestThreadCount) { largestThreadCount = t; } } taskExecutor.execute(task); synchronized (lock) { currentThreadCount--; } } finally { limitSemaphore.release(); } } }); if (thread == null) { throw Messages.msg.noThreadCreated(); } thread.start(); ok = true; } finally { if (! ok) semaphore.release(); } } catch (RejectedExecutionException e) { rejected.getAndIncrement(); throw e; } } public boolean isBlocking() { return blocking; } public void setBlocking(final boolean blocking) { this.blocking = blocking; } public int getLargestThreadCount() { synchronized (lock) { return largestThreadCount; } } public int getCurrentThreadCount() { synchronized (lock) { return currentThreadCount; } } /** {@inheritDoc} */ public int getQueueSize() { return 0; } public int getRejectedCount() { return rejected.get(); } public long getKeepAliveTime() { return 0L; } public void setKeepAliveTime(final long milliseconds) { if (milliseconds != 0L) { throw Messages.msg.keepAliveNotZero(); } } public String toString() { return String.format("%s (%s)", super.toString(), factory); } } jboss-threads-2.3.2.Final/src/main/java/org/jboss/threads/ThreadFormattedNameExecutor.java000066400000000000000000000027761325274360100315720ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2017 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.threads; class ThreadFormattedNameExecutor implements DirectExecutor { private final String nameFormat; private final DirectExecutor delegate; ThreadFormattedNameExecutor(final String nameFormat, final DirectExecutor delegate) { this.nameFormat = nameFormat; this.delegate = delegate; } public void execute(final Runnable command) { final JBossThread thr = JBossThread.currentThread(); final String oldName = thr.getName(); thr.setName(thr.getThreadNameInfo().format(thr, nameFormat)); try { delegate.execute(command); } finally { thr.setName(oldName); } } public String toString() { return String.format("%s format=\"%s\" -> %s", super.toString(), nameFormat, delegate); } }jboss-threads-2.3.2.Final/src/main/java/org/jboss/threads/ThreadLocalResetter.java000066400000000000000000000041131325274360100300600ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2017 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.threads; import java.lang.reflect.Field; import java.security.AccessController; final class ThreadLocalResetter implements Runnable { private static final ThreadLocalResetter INSTANCE = new ThreadLocalResetter(); private static final long threadLocalMapOffs; private static final long inheritableThreadLocalMapOffs; static { final Field threadLocals = AccessController.doPrivileged(new DeclaredFieldAction(Thread.class, "threadLocals")); threadLocalMapOffs = threadLocals == null ? 0 : JBossExecutors.unsafe.objectFieldOffset(threadLocals); final Field inheritableThreadLocals = AccessController.doPrivileged(new DeclaredFieldAction(Thread.class, "inheritableThreadLocals")); inheritableThreadLocalMapOffs = inheritableThreadLocals == null ? 0 : JBossExecutors.unsafe.objectFieldOffset(inheritableThreadLocals); } static ThreadLocalResetter getInstance() { return INSTANCE; } private ThreadLocalResetter() { } public void run() { final Thread thread = Thread.currentThread(); if (threadLocalMapOffs != 0) JBossExecutors.unsafe.putObject(thread, threadLocalMapOffs, null); if (inheritableThreadLocalMapOffs != 0) JBossExecutors.unsafe.putObject(thread, inheritableThreadLocalMapOffs, null); } public String toString() { return "Thread-local resetting Runnable"; } } jboss-threads-2.3.2.Final/src/main/java/org/jboss/threads/ThreadNameExecutor.java000066400000000000000000000026521325274360100277150ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2017 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ 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); } } jboss-threads-2.3.2.Final/src/main/java/org/jboss/threads/ThreadNameInfo.java000066400000000000000000000072171325274360100270140ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2017 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.threads; import java.util.regex.Pattern; import java.util.regex.Matcher; /** * Thread name information. */ final class ThreadNameInfo { private final long globalThreadSequenceNum; private final long perFactoryThreadSequenceNum; private final long factorySequenceNum; ThreadNameInfo(final long globalThreadSequenceNum, final long perFactoryThreadSequenceNum, final long factorySequenceNum) { this.globalThreadSequenceNum = globalThreadSequenceNum; this.perFactoryThreadSequenceNum = perFactoryThreadSequenceNum; this.factorySequenceNum = factorySequenceNum; } public long getGlobalThreadSequenceNum() { return globalThreadSequenceNum; } public long getPerFactoryThreadSequenceNum() { return perFactoryThreadSequenceNum; } public long getFactorySequenceNum() { return factorySequenceNum; } private static final Pattern searchPattern = Pattern.compile("([^%]+)|%."); /** * Format the thread name string. *
    *
  • {@code %%} - emit a percent sign
  • *
  • {@code %t} - emit the per-factory thread sequence number
  • *
  • {@code %g} - emit the global thread sequence number
  • *
  • {@code %f} - emit the factory sequence number
  • *
  • {@code %p} - emit the {@code ":"}-separated thread group path
  • *
  • {@code %i} - emit the thread ID
  • *
  • {@code %G} - emit the thread group name
  • *
* * @param thread the thread * @param formatString the format string * @return the thread name string */ public String format(Thread thread, String formatString) { final StringBuilder builder = new StringBuilder(formatString.length() * 5); final ThreadGroup group = thread.getThreadGroup(); final Matcher matcher = searchPattern.matcher(formatString); while (matcher.find()) { if (matcher.group(1) != null) { builder.append(matcher.group()); } else { switch (matcher.group().charAt(1)) { case '%': builder.append('%'); break; case 't': builder.append(perFactoryThreadSequenceNum); break; case 'g': builder.append(globalThreadSequenceNum); break; case 'f': builder.append(factorySequenceNum); break; case 'p': if (group != null) appendGroupPath(group, builder); break; case 'i': builder.append(thread.getId()); case 'G': if (group != null) builder.append(group.getName()); break; } } } return builder.toString(); } private static void appendGroupPath(ThreadGroup group, StringBuilder builder) { final ThreadGroup parent = group.getParent(); if (parent != null) { appendGroupPath(parent, builder); builder.append(':'); } builder.append(group.getName()); } } jboss-threads-2.3.2.Final/src/main/java/org/jboss/threads/ThreadNameNotatingExecutor.java000066400000000000000000000027541325274360100314240ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2017 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ 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); } } jboss-threads-2.3.2.Final/src/main/java/org/jboss/threads/UninterruptibleExecutor.java000066400000000000000000000020761325274360100311000ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2017 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.threads; import java.util.concurrent.Executor; class UninterruptibleExecutor implements Executor { private final Executor delegate; UninterruptibleExecutor(final Executor delegate) { this.delegate = delegate; } public void execute(final Runnable command) { JBossExecutors.executeUninterruptibly(delegate, command); } } jboss-threads-2.3.2.Final/src/main/java/org/jboss/threads/Version.java000066400000000000000000000046231325274360100256130ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2017 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.threads; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.nio.charset.StandardCharsets; import java.util.Properties; /** * */ public final class Version { private Version() { } private static final String JAR_NAME; private static final String VERSION_STRING; static { Properties versionProps = new Properties(); String jarName = "(unknown)"; String versionString = "(unknown)"; try (InputStream stream = Version.class.getResourceAsStream("Version.properties")) { if (stream != null) try (InputStreamReader reader = new InputStreamReader(stream, StandardCharsets.UTF_8)) { versionProps.load(reader); jarName = versionProps.getProperty("jarName", jarName); versionString = versionProps.getProperty("version", versionString); } } catch (IOException ignored) { } JAR_NAME = jarName; VERSION_STRING = versionString; try { Messages.msg.version(versionString); } catch (Throwable ignored) {} } /** * Get the name of the JBoss Modules JAR. * * @return the name */ public static String getJarName() { return JAR_NAME; } /** * Get the version string of JBoss Modules. * * @return the version string */ public static String getVersionString() { return VERSION_STRING; } /** * Print out the current version on {@code System.out}. * * @param args ignored */ public static void main(String[] args) { System.out.printf("JBoss Threads version %s\n", VERSION_STRING); } } jboss-threads-2.3.2.Final/src/main/java/org/jboss/threads/Version.properties000066400000000000000000000013531325274360100270630ustar00rootroot00000000000000# # JBoss, Home of Professional Open Source. # Copyright 2017 Red Hat, Inc., and individual contributors # as indicated by the @author tags. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # version=${project.version} jarName=${project.artifactId} jboss-threads-2.3.2.Final/src/main/java/org/jboss/threads/WrappingExecutor.java000066400000000000000000000030451325274360100274710ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2017 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.threads; import java.util.concurrent.RejectedExecutionException; import java.util.concurrent.Executor; /** * An executor which runs a task within the given direct executor. */ public interface WrappingExecutor extends Executor { /** * Run the given task directly, without a wrapper. * * @param task the task to run * @throws RejectedExecutionException if the execution was rejected for some reason */ void execute(Runnable task) throws RejectedExecutionException; /** * Run the given task within the given wrapper. * * @param directExecutor the task wrapper * @param task the task to run * @throws RejectedExecutionException if the execution was rejected for some reason */ void execute(DirectExecutor directExecutor, Runnable task) throws RejectedExecutionException; } jboss-threads-2.3.2.Final/src/main/java/org/jboss/threads/WrappingThreadFactory.java000066400000000000000000000025201325274360100304270ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2017 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ 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(JBossExecutors.executorTask(taskWrapper, r)); } public String toString() { return String.format("%s (%s) -> %s", super.toString(), taskWrapper, delegate); } } jboss-threads-2.3.2.Final/src/main/java/org/jboss/threads/management/000077500000000000000000000000001325274360100254325ustar00rootroot00000000000000BoundedQueueThreadPoolExecutorMBean.java000066400000000000000000000020001325274360100351770ustar00rootroot00000000000000jboss-threads-2.3.2.Final/src/main/java/org/jboss/threads/management/* * JBoss, Home of Professional Open Source. * Copyright 2017 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.threads.management; /** * */ @Deprecated public interface BoundedQueueThreadPoolExecutorMBean extends BoundedThreadPoolExecutorMBean { boolean isAllowCoreThreadTimeout(); void setAllowCoreThreadTimeout(boolean allow); int getCoreThreads(); void setCoreThreads(int newSize); } BoundedThreadPoolExecutorMBean.java000066400000000000000000000016331325274360100342050ustar00rootroot00000000000000jboss-threads-2.3.2.Final/src/main/java/org/jboss/threads/management/* * JBoss, Home of Professional Open Source. * Copyright 2017 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.threads.management; /** * */ @Deprecated public interface BoundedThreadPoolExecutorMBean extends ThreadPoolExecutorMBean { boolean isBlocking(); void setBlocking(boolean blocking); } ManageableThreadPoolExecutorService.java000066400000000000000000000025401325274360100352550ustar00rootroot00000000000000jboss-threads-2.3.2.Final/src/main/java/org/jboss/threads/management/* * JBoss, Home of Professional Open Source. * Copyright 2017 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.threads.management; import java.util.concurrent.ExecutorService; import org.wildfly.common.annotation.NotNull; /** * A thread pool for which an MBean can be obtained. */ public interface ManageableThreadPoolExecutorService extends ExecutorService { /** * Create or acquire an MXBean instance for this thread pool. Note that the thread pool itself will not * do anything in particular to register (or unregister) the MXBean with a JMX server; that is the caller's * responsibility. * * @return the MXBean instance (must not be {@code null}) */ @NotNull StandardThreadPoolMXBean getThreadPoolMXBean(); } jboss-threads-2.3.2.Final/src/main/java/org/jboss/threads/management/StandardThreadPoolMXBean.java000066400000000000000000000241641325274360100330610ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2017 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.threads.management; /** * An MXBean which contains the attributes and operations found on all standard thread pools. */ public interface StandardThreadPoolMXBean { /** * Get the pool size growth resistance factor. If the thread pool does not support growth resistance, * then {@code 0.0} (no resistance) is returned. * * @return the growth resistance factor ({@code 0.0 ≤ n ≤ 1.0}) */ float getGrowthResistance(); /** * Set the pool size growth resistance factor, if supported. * * @param value the growth resistance factor ({@code 0.0 ≤ n ≤ 1.0}) */ void setGrowthResistance(float value); /** * Determine whether the thread pool supports a growth resistance factor. * * @return {@code true} if the growth resistance factor is supported, {@code false} otherwise */ boolean isGrowthResistanceSupported(); /** * Get the core pool size. This is the size below which new threads will always be created if no idle threads * are available. If the thread pool does not support a separate core pool size, this size will match the * maximum size. * * @return the core pool size */ int getCorePoolSize(); /** * Set the core pool size. If the configured maximum pool size is less than the configured core size, the * core size will be reduced to match the maximum size when the thread pool is constructed. If the thread pool * does not support a separate core pool size, this setting will be ignored. * * @param corePoolSize the core pool size (must be greater than or equal to 0) */ void setCorePoolSize(int corePoolSize); /** * Determine whether this implementation supports a separate core pool size. * * @return {@code true} if a separate core size is supported; {@code false} otherwise */ boolean isCorePoolSizeSupported(); /** * Attempt to start a core thread without submitting work to it. * * @return {@code true} if the thread was started, or {@code false} if the pool is filled to the core size, the * thread could not be created, or prestart of core threads is not supported. */ boolean prestartCoreThread(); /** * Attempt to start all core threads. This is usually equivalent to calling {@link #prestartCoreThread()} in a loop * until it returns {@code false} and counting the {@code true} results. * * @return the number of started core threads (may be 0) */ int prestartAllCoreThreads(); /** * Determine whether this thread pool allows manual pre-start of core threads. * * @return {@code true} if pre-starting core threads is supported, {@code false} otherwise */ boolean isCoreThreadPrestartSupported(); /** * Get the maximum pool size. This is the absolute upper limit to the size of the thread pool. * * @return the maximum pool size */ int getMaximumPoolSize(); /** * Set the maximum pool size. If the configured maximum pool size is less than the configured core size, the * core size will be reduced to match the maximum size when the thread pool is constructed. * * @param maxPoolSize the maximum pool size (must be greater than or equal to 0) */ void setMaximumPoolSize(final int maxPoolSize); /** * Get an estimate of the current number of active threads in the pool. * * @return an estimate of the current number of active threads in the pool */ int getPoolSize(); /** * Get an estimate of the peak number of threads that the pool has ever held. * * @return an estimate of the peak number of threads that the pool has ever held */ int getLargestPoolSize(); /** * Get an estimate of the current number of active (busy) threads. * * @return an estimate of the active count */ int getActiveCount(); /** * Determine whether core threads are allowed to time out. A "core thread" is defined as any thread in the pool * when the pool size is below the pool's {@linkplain #getCorePoolSize() core pool size}. If the thread pool * does not support a separate core pool size, this method should return {@code false}. *

* This method is named differently from the typical {@code allowsCoreThreadTimeOut()} in order to accommodate * the requirements of MXBean attribute methods. * * @return {@code true} if core threads are allowed to time out, {@code false} otherwise */ boolean isAllowCoreThreadTimeOut(); /** * Establish whether core threads are allowed to time out. A "core thread" is defined as any thread in the pool * when the pool size is below the pool's {@linkplain #getCorePoolSize() core pool size}. If the thread pool * does not support a separate core pool size, the value is ignored. *

* This method is named differently from the typical {@code allowCoreThreadTimeOut(boolean)} in order to accommodate * the requirements of MXBean attribute methods. * * @param value {@code true} if core threads are allowed to time out, {@code false} otherwise */ void setAllowCoreThreadTimeOut(boolean value); /** * Get the thread keep-alive time, in seconds. *

* This method differs from the typical {@code getKeepAliveTime(TimeUnit)} due to the inability to send in a * time units parameter on an MXBean attribute. As such, the unit is hard-coded to seconds. * * @return the thread keep-alive time, in seconds */ long getKeepAliveTimeSeconds(); /** * Set the thread keep-alive time, in seconds. *

* This method differs from the typical {@code getKeepAliveTime(TimeUnit)} due to the inability to send in a * time units parameter on an MXBean attribute. As such, the unit is hard-coded to seconds. * * @param seconds the thread keep-alive time, in seconds (must be greater than or equal to 0) */ void setKeepAliveTimeSeconds(long seconds); /** * Get the maximum queue size for this thread pool. If there is no queue or it is not bounded, {@link Integer#MAX_VALUE} is * returned. * * @return the maximum queue size */ int getMaximumQueueSize(); /** * Set the maximum queue size for this thread pool. If the new maximum queue size is smaller than the current queue * size, there is no effect other than preventing tasks from being enqueued until the size decreases below the * maximum again. If changing the maximum queue size is not supported, or there is no bounded backing queue, * then the value is ignored. * * @param size the maximum queue size for this thread pool */ void setMaximumQueueSize(int size); /** * Get an estimate of the current queue size, if any. If no backing queue exists, or its size cannot be determined, * this method will return 0. * * @return an estimate of the current queue size */ int getQueueSize(); /** * Get an estimate of the peak size of the queue, if any. If no backing queue exists, or its size cannot be determined, * this method will return 0. * * @return an estimate of the peak size of the queue */ int getLargestQueueSize(); /** * Determine whether there is a bounded queue backing this thread pool. * * @return {@code true} if there is a bounded backing queue, {@code false} otherwise */ boolean isQueueBounded(); /** * Determine whether the maximum queue size is modifiable. * * @return {@code true} if the queue size is modifiable, false otherwise */ boolean isQueueSizeModifiable(); /** * Determine whether shutdown was requested. * * @return {@code true} if shutdown was requested, {@code false} otherwise */ boolean isShutdown(); /** * Determine whether shutdown is in progress. * * @return {@code true} if shutdown is in progress, {@code false} otherwise */ boolean isTerminating(); /** * Determine whether shutdown is complete. * * @return {@code true} if shutdown is complete, {@code false} otherwise */ boolean isTerminated(); /** * Get an estimate of the total number of tasks ever submitted to this thread pool. This number may be zero * if the underlying thread pool does not support this metric. * * @return an estimate of the total number of tasks ever submitted to this thread pool */ long getSubmittedTaskCount(); /** * Get an estimate of the total number of tasks ever rejected by this thread pool for any reason. This number may be zero * if the underlying thread pool does not support this metric. * * @return an estimate of the total number of tasks ever rejected by this thread pool */ long getRejectedTaskCount(); /** * Get an estimate of the number of tasks completed by this thread pool. This number may be zero * if the underlying thread pool does not support this metric. * * @return an estimate of the number of tasks completed by this thread pool */ long getCompletedTaskCount(); /** * Get the number of spin misses that have occurred. Spin misses indicate that contention is not being properly * handled by the thread pool. * * @return an estimate of the number of spin misses */ default long getSpinMissCount() { return 0; } } jboss-threads-2.3.2.Final/src/main/java/org/jboss/threads/management/ThreadExecutorMBean.java000066400000000000000000000016451325274360100321340ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2017 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.threads.management; /** * */ @Deprecated public interface ThreadExecutorMBean { int getRejectedCount(); int getCurrentThreadCount(); int getLargestThreadCount(); int getQueueSize(); } jboss-threads-2.3.2.Final/src/main/java/org/jboss/threads/management/ThreadPoolExecutorMBean.java000066400000000000000000000017271325274360100327670ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2017 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.threads.management; /** * */ @Deprecated public interface ThreadPoolExecutorMBean extends ThreadExecutorMBean { int getMaxThreads(); void setMaxThreads(int newSize); long getKeepAliveTime(); void setKeepAliveTime(long milliseconds); } jboss-threads-2.3.2.Final/src/test/000077500000000000000000000000001325274360100170675ustar00rootroot00000000000000jboss-threads-2.3.2.Final/src/test/java/000077500000000000000000000000001325274360100200105ustar00rootroot00000000000000jboss-threads-2.3.2.Final/src/test/java/org/000077500000000000000000000000001325274360100205775ustar00rootroot00000000000000jboss-threads-2.3.2.Final/src/test/java/org/jboss/000077500000000000000000000000001325274360100217175ustar00rootroot00000000000000jboss-threads-2.3.2.Final/src/test/java/org/jboss/threads/000077500000000000000000000000001325274360100233515ustar00rootroot00000000000000jboss-threads-2.3.2.Final/src/test/java/org/jboss/threads/ArrayQueueTestCase.java000066400000000000000000000065261325274360100277440ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2017 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.threads; import junit.framework.TestCase; /** * */ public final class ArrayQueueTestCase extends TestCase { public void testBasic() { final int max = 40; final ArrayQueue queue = new ArrayQueue(max); for (int i = 0; i < max; i ++) { assertEquals("Size mismatch, iteration " + i, i, queue.size()); assertTrue("Iteration " + i, queue.offer(new Object())); } assertFalse("Queue took extra element", queue.offer(new Object())); for (int i = 0; i < max; i ++) { assertNotNull("Queue missing elements", queue.poll()); } assertNull("Queue has extra elements", queue.poll()); } public void testContents() { final int max = 40; final ArrayQueue queue = new ArrayQueue(max); for (int cnt = 1; cnt < max; cnt ++) { for (int i = 0; i < cnt; i ++) { assertEquals("Size mismatch, iteration " + i, i, queue.size()); assertTrue("Queue won't take element, iteration " + cnt + "/" + i, queue.offer(new Integer(i))); } for (int i = 0; i < cnt; i ++) { assertTrue("Missing int value, iteration " + cnt + "/" + i, queue.contains(new Integer(i))); } for (int i = 0; i < cnt; i ++) { assertEquals("Size mismatch, iteration " + i, cnt - i, queue.size()); assertEquals("Wrong object value, iteration " + cnt + "/" + i, new Integer(i), queue.poll()); } assertNull("Extra value, iteration " + cnt, queue.poll()); for (int i = 0; i < cnt; i ++) { assertFalse("Nonremoved value, iteration " + cnt + "/" + i, queue.contains(new Integer(i))); } } } public void testClear() { final int max = 40; final ArrayQueue queue = new ArrayQueue(max); for (int cnt = 1; cnt < max; cnt ++) { for (int i = 0; i < cnt; i ++) { assertEquals("Size mismatch, iteration " + i, i, queue.size()); assertTrue("Queue won't take element, iteration " + cnt + "/" + i, queue.offer(new Integer(i))); } for (int i = 0; i < cnt; i ++) { assertTrue("Missing int value, iteration " + cnt + "/" + i, queue.contains(new Integer(i))); } queue.clear(); assertNull("Extra value, iteration " + cnt, queue.poll()); for (int i = 0; i < cnt; i ++) { assertFalse("Nonremoved value, iteration " + cnt + "/" + i, queue.contains(new Integer(i))); } } } } jboss-threads-2.3.2.Final/src/test/java/org/jboss/threads/DeferredInterruptTestCase.java000066400000000000000000000044621325274360100313130ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2017 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.threads; import java.util.concurrent.CountDownLatch; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.locks.LockSupport; import junit.framework.TestCase; /** * @author David M. Lloyd */ public class DeferredInterruptTestCase extends TestCase { public void testDeferral() throws Exception { final AtomicBoolean delivered0 = new AtomicBoolean(); final AtomicBoolean deferred = new AtomicBoolean(); final AtomicBoolean delivered = new AtomicBoolean(); final CountDownLatch latch1 = new CountDownLatch(1); final CountDownLatch latch2 = new CountDownLatch(1); final JBossThread thread = new JBossThread(new Runnable() { public void run() { Thread.interrupted(); latch1.countDown(); LockSupport.parkNanos(3000000000L); delivered0.set(Thread.interrupted()); JBossThread.executeWithInterruptDeferred(new Runnable() { public void run() { latch2.countDown(); LockSupport.parkNanos(500000000L); deferred.set(! Thread.interrupted()); } }); delivered.set(Thread.interrupted()); } }); thread.start(); latch1.await(); thread.interrupt(); latch2.await(); thread.interrupt(); thread.join(); assertTrue(delivered0.get()); assertTrue(deferred.get()); assertTrue(delivered.get()); } } jboss-threads-2.3.2.Final/src/test/java/org/jboss/threads/EnhancedThreadQueueExecutorTestCase.java000066400000000000000000000051231325274360100332320ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2018 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.threads; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; import org.junit.Assert; import org.junit.Test; public class EnhancedThreadQueueExecutorTestCase { @Test public void testEnhancedExecutorShutdownNoTasks() throws Exception { final CountDownLatch terminateLatch = new CountDownLatch(1); EnhancedQueueExecutor executor = new EnhancedQueueExecutor.Builder() .setCorePoolSize(10) .setKeepAliveTime(1, TimeUnit.NANOSECONDS) .setTerminationTask(new Runnable() { @Override public void run() { terminateLatch.countDown(); } }) .build(); executor.shutdown(); Assert.assertTrue(terminateLatch.await(10, TimeUnit.SECONDS)); } @Test //JBTHR-50 public void testEnhancedExecutorShutdown() throws Exception { final CountDownLatch terminateLatch = new CountDownLatch(1); EnhancedQueueExecutor executor = new EnhancedQueueExecutor.Builder() .setCorePoolSize(10) .setKeepAliveTime(1, TimeUnit.NANOSECONDS) .setTerminationTask(new Runnable() { @Override public void run() { terminateLatch.countDown(); } }) .build(); for(int i = 0; i < 10000; ++i) { executor.submit(new Runnable() { @Override public void run() { try { Thread.sleep(1); } catch (InterruptedException e) { //ignore } } }); } executor.shutdown(); Assert.assertTrue(terminateLatch.await(10, TimeUnit.SECONDS)); } } jboss-threads-2.3.2.Final/src/test/java/org/jboss/threads/ThreadFactoryTestCase.java000066400000000000000000000135441325274360100304160ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2017 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.threads; import junit.framework.TestCase; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.CountDownLatch; /** * */ public final class ThreadFactoryTestCase extends TestCase { private static final NullRunnable NULL_RUNNABLE = new NullRunnable(); private static class NullRunnable implements Runnable { public void run() { } } private static void doTestNamePattern(JBossThreadFactory threadFactory, int expectedPerFactoryId, int expectedGlobalId, int expectedFactoryId) { final String name = threadFactory.newThread(NULL_RUNNABLE).getName(); assertTrue("Wrong thread name (" + name + ") ", name.matches("-([a-z]+:)*one:two:three-%-" + expectedPerFactoryId + "-" + expectedGlobalId + "-" + expectedFactoryId + "-")); } /** * This MUST be the first test, otherwise the sequence numbers will be wrong. */ public void testNamePattern() { // TODO - skip test for now since it depends on order. if (true) return; final JBossThreadFactory threadFactory1 = new JBossThreadFactory(new ThreadGroup(new ThreadGroup(new ThreadGroup("one"), "two"), "three"), null, null, "-%p-%%-%t-%g-%f-", null, null); doTestNamePattern(threadFactory1, 1, 1, 1); doTestNamePattern(threadFactory1, 2, 2, 1); doTestNamePattern(threadFactory1, 3, 3, 1); final JBossThreadFactory threadFactory2 = new JBossThreadFactory(new ThreadGroup(new ThreadGroup(new ThreadGroup("one"), "two"), "three"), null, null, "-%p-%%-%t-%g-%f-", null, null); doTestNamePattern(threadFactory2, 1, 4, 2); doTestNamePattern(threadFactory2, 2, 5, 2); doTestNamePattern(threadFactory2, 3, 6, 2); doTestNamePattern(threadFactory2, 4, 7, 2); // back to the first factory... doTestNamePattern(threadFactory1, 4, 8, 1); } public void testDaemon() { final JBossThreadFactory threadFactory1 = new JBossThreadFactory(null, Boolean.TRUE, null, "%t", null, null); assertTrue("Thread is not a daemon thread", threadFactory1.newThread(NULL_RUNNABLE).isDaemon()); final JBossThreadFactory threadFactory2 = new JBossThreadFactory(null, Boolean.FALSE, null, "%t", null, null); assertFalse("Thread should not be a daemon thread", threadFactory2.newThread(NULL_RUNNABLE).isDaemon()); } public void testInterruptHandler() throws InterruptedException { final AtomicBoolean wasInterrupted = new AtomicBoolean(); final AtomicBoolean called = new AtomicBoolean(); final CountDownLatch latch = new CountDownLatch(1); final JBossThreadFactory threadFactory = new JBossThreadFactory(null, null, null, null, null, null); final Thread t = threadFactory.newThread(new Runnable() { public void run() { synchronized (this) { final InterruptHandler old = JBossThread.getAndSetInterruptHandler(new InterruptHandler() { public void handleInterrupt(final Thread thread) { called.set(true); } }); try { latch.countDown(); wait(); } catch (InterruptedException e) { wasInterrupted.set(true); } finally { JBossThread.getAndSetInterruptHandler(old); } } } }); t.start(); latch.await(); t.interrupt(); t.join(); assertTrue("Was not interrupted", wasInterrupted.get()); assertTrue("Handler was not called", called.get()); } public void testUncaughtHandler() throws InterruptedException { final AtomicBoolean called = new AtomicBoolean(); final JBossThreadFactory factory = new JBossThreadFactory(null, null, null, null, new Thread.UncaughtExceptionHandler() { public void uncaughtException(final Thread t, final Throwable e) { called.set(true); } }, null); final Thread t = factory.newThread(new Runnable() { public void run() { throw new RuntimeException("..."); } }); t.start(); t.join(); assertTrue("Handler was not called", called.get()); } public void testInitialPriority() { assertEquals("Wrong initial thread priority", 1, new JBossThreadFactory(null, null, Integer.valueOf(1), null, null, null).newThread(NULL_RUNNABLE).getPriority()); assertEquals("Wrong initial thread priority", 2, new JBossThreadFactory(null, null, Integer.valueOf(2), null, null, null).newThread(NULL_RUNNABLE).getPriority()); final ThreadGroup grp = new ThreadGroup("blah"); grp.setMaxPriority(5); assertEquals("Wrong initial thread priority", 5, new JBossThreadFactory(grp, null, Integer.valueOf(10), null, null, null).newThread(NULL_RUNNABLE).getPriority()); assertEquals("Wrong initial thread priority", 1, new JBossThreadFactory(grp, null, Integer.valueOf(1), null, null, null).newThread(NULL_RUNNABLE).getPriority()); } } jboss-threads-2.3.2.Final/src/test/java/org/jboss/threads/ThreadPoolTestCase.java000066400000000000000000000325331325274360100277170ustar00rootroot00000000000000/* * JBoss, Home of Professional Open Source. * Copyright 2017 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.threads; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutorService; import java.util.concurrent.RejectedExecutionException; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; import junit.framework.TestCase; /** * */ public final class ThreadPoolTestCase extends TestCase { private final JBossThreadFactory threadFactory = new JBossThreadFactory(null, null, null, "test thread %p %t", null, null); private static final class SimpleTask implements Runnable { private final CountDownLatch taskUnfreezer; private final CountDownLatch taskFinishLine; private SimpleTask(final CountDownLatch taskUnfreezer, final CountDownLatch taskFinishLine) { this.taskUnfreezer = taskUnfreezer; this.taskFinishLine = taskFinishLine; } public void run() { try { assertTrue(taskUnfreezer.await(800L, TimeUnit.MILLISECONDS)); } catch (InterruptedException e) { fail("interrupted"); } taskFinishLine.countDown(); } } public void testBasic() throws InterruptedException { // Start some tasks, let them run, then shut down the executor final int cnt = 100; final CountDownLatch taskUnfreezer = new CountDownLatch(1); final CountDownLatch taskFinishLine = new CountDownLatch(cnt); final ExecutorService simpleQueueExecutor = new QueueExecutor(5, 5, 500L, TimeUnit.MILLISECONDS, 1000, threadFactory, true, null); for (int i = 0; i < cnt; i ++) { simpleQueueExecutor.execute(new SimpleTask(taskUnfreezer, taskFinishLine)); } taskUnfreezer.countDown(); final boolean finished = taskFinishLine.await(800L, TimeUnit.MILLISECONDS); assertTrue(finished); simpleQueueExecutor.shutdown(); try { simpleQueueExecutor.execute(new Runnable() { public void run() { } }); fail("Task not rejected after shutdown"); } catch (Throwable t) { assertTrue(t instanceof RejectedExecutionException); } assertTrue(simpleQueueExecutor.awaitTermination(800L, TimeUnit.MILLISECONDS)); } public void testShutdownNow() throws InterruptedException { final AtomicBoolean interrupted = new AtomicBoolean(); final AtomicBoolean ran = new AtomicBoolean(); final CountDownLatch startLatch = new CountDownLatch(1); final CountDownLatch finLatch = new CountDownLatch(1); final ExecutorService simpleQueueExecutor = new QueueExecutor(5, 5, 500L, TimeUnit.MILLISECONDS, 1000, threadFactory, true, null); simpleQueueExecutor.execute(new Runnable() { public void run() { try { ran.set(true); startLatch.countDown(); Thread.sleep(5000L); } catch (InterruptedException e) { interrupted.set(true); } finally { finLatch.countDown(); } } }); assertTrue("Task not started", startLatch.await(300L, TimeUnit.MILLISECONDS)); assertTrue("Task returned", simpleQueueExecutor.shutdownNow().isEmpty()); try { simpleQueueExecutor.execute(new Runnable() { public void run() { } }); fail("Task not rejected after shutdown"); } catch (RejectedExecutionException t) { } assertTrue("Task not finished", finLatch.await(300L, TimeUnit.MILLISECONDS)); assertTrue("Executor not shut down in 800ms", simpleQueueExecutor.awaitTermination(800L, TimeUnit.MILLISECONDS)); assertTrue("Task wasn't run", ran.get()); assertTrue("Worker wasn't interrupted", interrupted.get()); } private static class Holder { private T instance; public Holder(T instance) { this.instance = instance; } public T get() { return instance; } public void set(T instance) {this.instance = instance;} } public void testBlocking() throws InterruptedException { final int queueSize = 20; final int coreThreads = 5; final int extraThreads = 5; final int cnt = queueSize + coreThreads + extraThreads; final CountDownLatch taskUnfreezer = new CountDownLatch(1); final CountDownLatch taskFinishLine = new CountDownLatch(cnt); final ExecutorService simpleQueueExecutor = new QueueExecutor(coreThreads, coreThreads + extraThreads, 500L, TimeUnit.MILLISECONDS, new ArrayQueue(queueSize), threadFactory, true, null); for (int i = 0; i < cnt; i ++) { simpleQueueExecutor.execute(new SimpleTask(taskUnfreezer, taskFinishLine)); } Thread.currentThread().interrupt(); try { simpleQueueExecutor.execute(new Runnable() { public void run() { } }); fail("Task was accepted"); } catch (RejectedExecutionException t) { } Thread.interrupted(); final CountDownLatch latch = new CountDownLatch(1); final Thread otherThread = threadFactory.newThread(new Runnable() { public void run() { simpleQueueExecutor.execute(new Runnable() { public void run() { latch.countDown(); } }); } }); otherThread.start(); assertFalse("Task executed without wait", latch.await(100L, TimeUnit.MILLISECONDS)); // safe to say the other thread is blocking...? taskUnfreezer.countDown(); assertTrue("Task never ran", latch.await(800L, TimeUnit.MILLISECONDS)); otherThread.join(500L); assertTrue("Simple Tasks never ran", taskFinishLine.await(800L, TimeUnit.MILLISECONDS)); simpleQueueExecutor.shutdown(); final Holder callback = new Holder(false); final CountDownLatch shutdownLatch = new CountDownLatch(1); ((QueueExecutor)simpleQueueExecutor).addShutdownListener(new EventListener() { @Override public void handleEvent(Object attachment) { callback.set(true); shutdownLatch.countDown(); } } , null); shutdownLatch.await(100L, TimeUnit.MILLISECONDS); assertTrue("Calback not called", callback.get()); assertTrue("Executor not shut down in 800ms", simpleQueueExecutor.awaitTermination(800L, TimeUnit.MILLISECONDS)); } public void testBlockingEmpty() throws InterruptedException { final int queueSize = 20; final int coreThreads = 5; final int extraThreads = 5; final int cnt = queueSize + coreThreads + extraThreads; final ExecutorService simpleQueueExecutor = new QueueExecutor(coreThreads, coreThreads + extraThreads, 500L, TimeUnit.MILLISECONDS, new ArrayQueue(queueSize), threadFactory, true, null); simpleQueueExecutor.shutdown(); final Holder callback = new Holder(false); ((QueueExecutor)simpleQueueExecutor).addShutdownListener(new EventListener() { @Override public void handleEvent(Object attachment) { callback.set(true); } } , null); assertTrue("Calback not called", callback.get()); assertTrue("Executor not shut down in 800ms", simpleQueueExecutor.awaitTermination(800L, TimeUnit.MILLISECONDS)); Thread.interrupted(); } public void testQueuelessEmpty() throws InterruptedException { final int queueSize = 20; final int coreThreads = 5; final int extraThreads = 5; final int cnt = queueSize + coreThreads + extraThreads; final ExecutorService simpleQueueExecutor = new QueuelessExecutor(threadFactory, SimpleDirectExecutor.INSTANCE, null, 500L); simpleQueueExecutor.shutdown(); final Holder callback = new Holder(false); ((QueuelessExecutor)simpleQueueExecutor).addShutdownListener(new EventListener() { @Override public void handleEvent(Object attachment) { callback.set(true); } } , null); assertTrue("Calback not called", callback.get()); assertTrue("Executor not shut down in 800ms", simpleQueueExecutor.awaitTermination(800L, TimeUnit.MILLISECONDS)); Thread.interrupted(); } public void testQueuelessKeepAlive() throws InterruptedException { // Test for https://issues.jboss.org/browse/JBTHR-32 QueuelessExecutor doesn't shrink with keepAliveTime final QueuelessExecutor simpleQueuelessExecutor = new QueuelessExecutor(threadFactory, SimpleDirectExecutor.INSTANCE, null, 100L); simpleQueuelessExecutor.setMaxThreads(1); final Holder thread1 = new Holder(null); simpleQueuelessExecutor.execute(new Runnable() { boolean first = true; public void run() { thread1.set(Thread.currentThread()); } }); try { Thread.sleep(500L); } catch (InterruptedException ignore) { } final CountDownLatch latch = new CountDownLatch(1); final Holder thread2 = new Holder(null); simpleQueuelessExecutor.execute(new Runnable() { public void run() { thread2.set(Thread.currentThread()); latch.countDown(); } }); latch.await(100L, TimeUnit.MILLISECONDS); assertTrue("First task and second task should be executed on different threads", thread1.get() != thread2.get()); simpleQueuelessExecutor.shutdown(); assertTrue("Executor not shut down in 800ms", simpleQueuelessExecutor.awaitTermination(800L, TimeUnit.MILLISECONDS)); Thread.interrupted(); } public void testQueuelessKeepAliveRepeating() throws InterruptedException { // Test for https://issues.jboss.org/browse/JBTHR-23 QueuelessExecutor repeats to execute previous runnable final QueuelessExecutor simpleQueuelessExecutor = new QueuelessExecutor(threadFactory, SimpleDirectExecutor.INSTANCE, null, 100L); simpleQueuelessExecutor.setMaxThreads(1); final CountDownLatch latch = new CountDownLatch(1); simpleQueuelessExecutor.execute(new Runnable() { public void run() { latch.countDown(); } }); latch.await(100L, TimeUnit.MILLISECONDS); final Holder callback = new Holder(false); simpleQueuelessExecutor.execute(new Runnable() { boolean first = true; public void run() { callback.set(true); if (!first) { callback.set(false); } first = false; } }); try { Thread.sleep(500L); } catch (InterruptedException ignore) { } simpleQueuelessExecutor.shutdown(); assertTrue("Calback only called once", callback.get()); assertTrue("Executor not shut down in 800ms", simpleQueuelessExecutor.awaitTermination(800L, TimeUnit.MILLISECONDS)); Thread.interrupted(); } public void testQueueRejection() throws InterruptedException { final int queueSize = 1; final int coreThreads = 1; final int extraThreads = 0; final int cnt = queueSize + coreThreads + extraThreads; final ExecutorService queueExecutor = new QueueExecutor(coreThreads, coreThreads + extraThreads, 500L, TimeUnit.MILLISECONDS, queueSize, threadFactory, false, null); final CountDownLatch taskUnfreezer = new CountDownLatch(1); final Runnable task = new Runnable() { public void run() { boolean running = true; while (running) { try { taskUnfreezer.await(); running = false; } catch (InterruptedException e) { } } } }; try { try { for (int i = 0; i < cnt; i++) { queueExecutor.execute(task); } } catch (RejectedExecutionException e) { fail("unexpected RejectedExecutionException"); } try { queueExecutor.execute(task); fail("Task not rejected after too many tasks"); } catch (RejectedExecutionException e) { // expected } } finally { taskUnfreezer.countDown(); queueExecutor.shutdown(); } } } jboss-threads-2.3.2.Final/src/test/resources/000077500000000000000000000000001325274360100211015ustar00rootroot00000000000000jboss-threads-2.3.2.Final/src/test/resources/logging.properties000066400000000000000000000030731325274360100246500ustar00rootroot00000000000000# # JBoss, Home of Professional Open Source. # Copyright 2017 Red Hat, Inc., and individual contributors # as indicated by the @author tags. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # # Additional logger names to configure (root logger is always configured) loggers=org.jboss.threads # Root logger configuration logger.level=INFO logger.handlers=CONSOLE, FILE logger.org.jboss.threads.level=${test.level:INFO} # Console handler configuration handler.CONSOLE=org.jboss.logmanager.handlers.ConsoleHandler handler.CONSOLE.properties=autoFlush handler.CONSOLE.level=ALL handler.CONSOLE.autoFlush=true handler.CONSOLE.formatter=PATTERN # File handler configuration handler.FILE=org.jboss.logmanager.handlers.FileHandler handler.FILE.level=ALL handler.FILE.properties=autoFlush,fileName handler.FILE.autoFlush=true handler.FILE.fileName=./target/test.log handler.FILE.formatter=PATTERN # Formatter pattern configuration formatter.PATTERN=org.jboss.logmanager.formatters.PatternFormatter formatter.PATTERN.properties=pattern formatter.PATTERN.pattern=%d{HH:mm:ss,SSS} %-5p [%c] (%t) %s%e%n