001/*
002 * Trident - A Multithreaded Server Alternative
003 * Copyright 2014 The TridentSDK Team
004 *
005 * Licensed under the Apache License, Version 2.0 (the "License");
006 * you may not use this file except in compliance with the License.
007 * You may obtain a copy of the License at
008 *
009 *    http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017
018package net.tridentsdk.concurrent;
019
020import javax.annotation.Nonnull;
021import javax.annotation.concurrent.ThreadSafe;
022import java.util.List;
023import java.util.concurrent.Callable;
024import java.util.concurrent.Executor;
025import java.util.concurrent.Future;
026
027/**
028 * A tunable task executor which represents a scalable thread pool
029 *
030 * <p>This class contains 3 selection methods:
031 * <ul>
032 *   <li>Core: Selects a non-dying thread</li>
033 *   <li>Next: Selects a thread, might be non-dying</li>
034 *   <li>Scaled: Creates a new thread if all workers are occupied and the count is below maxThreads. Otherwise returns nextThread.</li>
035 * </ul></p>
036 *
037 * @author The TridentSDK Team
038 * @since 0.3-alpha-DP
039 */
040@ThreadSafe
041public interface SelectableThreadPool extends Executor {
042    /**
043     * The maximum amount of expiring concurrent plus non-dying concurrent which are created when executing tasks or finding a scaled thread when
044     * existing workers are occupied
045     *
046     * @return the maximum scale, by default {@code 50}
047     */
048    int maxThreads();
049
050    /**
051     * Sets the maximum scale (explained in {@link #maxThreads()}
052     *
053     * @param maxScale the maximum extra scaling concurrent
054     */
055    void setMaxThreads(int maxScale);
056
057    /**
058     * The interval at which an <em>expiring</em> worker will die after inactivity
059     *
060     * @return the time, in milliseconds, which will need to elapse before an expiring worker dies
061     */
062    long threadExpiryTime();
063
064    /**
065     * Sets the interval at which an expiring worker will die after inactivity
066     *
067     * @param expireIntervalMillis the interval, in milliseconds
068     */
069    void setThreadExpiryTime(long expireIntervalMillis);
070
071    /**
072     * Obtains whether an expiring worker will check the task list size before dieing
073     *
074     * @return {@code true} (default) to indiciate the worker does check the task list size
075     */
076    boolean mustEmptyBeforeExpire();
077
078    /**
079     * Ensures there are no tasks in an expiring worker before it dies
080     *
081     * @param mustEmptyBeforeExpire {@code true} (default) if the worker needs to ensure the task list is empty
082     */
083    void setMustEmptyBeforeExpire(boolean mustEmptyBeforeExpire);
084
085    /**
086     * Selects a thread in much the same way as {@link #selectNext()}, however, it does not include concurrent that have been
087     * added to the scaling pool.
088     *
089     * <p>This is useful for caching SelectableThreads for thread-confinement</p>
090     *
091     * @return the next selected thread
092     */
093    SelectableThread selectCore();
094
095    /**
096     * Obtains a worker which is available in the thread pool
097     *
098     * <p>Unlike using {@link #selectScaled()}, this does not create a new thread if all workers are occupied.</p>
099     *
100     * <p>Obtaining an executor and immediately adding a task is a broken idiom.
101     * Store the executor, or use {@link #execute(Runnable)}</p>
102     *
103     * @return the next worker in the pool
104     */
105    SelectableThread selectNext();
106
107    /**
108     * Obtains an unoccupied thread, or if none exists, create a new thread
109     *
110     * <p>The new thread, if created, will expire. The default time is 60 seconds, if there are no tasks left.
111     * The timer is not renewed if there are still tasks. The timer is a lazy {@code long} stamp set when tasks are polled
112     * if the worker wakes up spuriously or a task is added.</p>
113     *
114     * <p>Obtaining an executor and immediately adding a task is a broken idiom.
115     * Store the executor, or use {@link #execute(Runnable)}</p>
116     *
117     * @return the thread which is unoccupied when observed
118     */
119    SelectableThread selectScaled();
120
121    /**
122     * Lists all available task executors from the concurrent
123     *
124     * @return the thread list
125     */
126    List<SelectableThread> workers();
127
128    /**
129     * Adds support for running a runnable with callback
130     *
131     * @param callable the callback to run
132     * @return the result of the task, before it has finished
133     */
134    @Nonnull
135    <V> Future<V> submit(Callable<V> callable);
136
137    /**
138     * Shuts down the thread processes
139     */
140    void shutdown();
141}