001/*
002 * ============================================================================
003 *  Copyright © 2002-2022 by Thomas Thrien.
004 *  All Rights Reserved.
005 * ============================================================================
006 *  Licensed to the public under the agreements of the GNU Lesser General Public
007 *  License, version 3.0 (the "License"). You may obtain a copy of the License at
008 *
009 *       http://www.gnu.org/licenses/lgpl.html
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, WITHOUT
013 *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
014 *  License for the specific language governing permissions and limitations
015 *  under the License.
016 */
017
018package org.tquadrat.foundation.lang;
019
020import static org.apiguardian.api.API.Status.STABLE;
021
022import java.lang.Thread.UncaughtExceptionHandler;
023import java.util.concurrent.ThreadFactory;
024import java.util.function.IntFunction;
025
026import org.apiguardian.api.API;
027import org.tquadrat.foundation.annotation.ClassVersion;
028import org.tquadrat.foundation.exception.ValidationException;
029import org.tquadrat.foundation.lang.internal.ThreadFactoryBuilderImpl;
030
031/**
032 *  <p>{@summary A builder for an implementation of
033 *  {@link ThreadFactory}.}</p>
034 *  <p>All values are optional, but {@code null} is no valid argument value for
035 *  any method in this API.</p>
036 *  <p>The simplest use case to get a valid
037 *  {@link ThreadFactory}
038 *  instance is</p>
039 *  <pre><code>final var threadFactory = ThreadFactoryBuilder.obtainBuilder()
040 *    .build();</code></pre>
041 *
042 *  @extauthor Thomas Thrien - thomas.thrien@tquadrat.org
043 *  @version $Id: ThreadFactoryBuilder.java 1118 2024-03-15 16:14:15Z tquadrat $
044 *  @since 0.1.0
045 *
046 *  @UMLGraph.link
047 */
048@ClassVersion( sourceVersion = "$Id: ThreadFactoryBuilder.java 1118 2024-03-15 16:14:15Z tquadrat $" )
049@API( status = STABLE, since = "0.1.0" )
050public sealed interface ThreadFactoryBuilder
051    permits ThreadFactoryBuilderImpl
052{
053        /*---------*\
054    ====** Methods **==========================================================
055        \*---------*/
056    /**
057     *  Creates the instance of
058     *  {@link java.util.concurrent.ThreadFactory}.
059     *
060     *  @return The thread factory.
061     */
062    public ThreadFactory build();
063
064    /**
065     *  Returns an instance of the builder.
066     *
067     *  @return A thread factory builder.
068     */
069    public static ThreadFactoryBuilder obtainBuilder() { return new ThreadFactoryBuilderImpl(); }
070
071    /**
072     *  <p>{@summary Sets the context class loader for the new threads created
073     *  by the new thread factory.}</p>
074     *  <p>The context class loader allows the creator of the thread to provide
075     *  the appropriate class loader, through
076     *  {@link Thread#getContextClassLoader()},
077     *  to code running in the thread when loading classes and resources.</p>
078     *  <p>If not set, new threads will use the system class loader (or,
079     *  failing that, the bootstrap class loader).</p>
080     *
081     *  @param  contextClassLoader  The context classloader.
082     *  @return The builder.
083     *
084     *  @see Thread#setContextClassLoader(ClassLoader)
085     */
086    public ThreadFactoryBuilder setContextClassLoader( final ClassLoader contextClassLoader );
087
088    /**
089     *  <p>{@summary Sets the flag that controls whether the new threads,
090     *  created by the new thread factory, will suppress, or not, the
091     *  inheriting of initial values for
092     *  {@linkplain InheritableThreadLocal inheritable thread-local variables}
093     *  from the constructing thread.} This allows for finer grain control over
094     *  inheritable thread-locals. Care must be taken when setting the flag to
095     *  {@code false}, as it may lead to unexpected behavior if the new thread
096     *  executes code that expects a specific thread-local value to be
097     *  inherited.</p>
098     *  <p>If not set, the value for the new threads will be {@code true}.</p>
099     *
100     *  @param  flag    {@code true} if the values for inheritable thread
101     *      locals will be inherited, {@code false} to disable this feature.
102     *  @return The builder.
103     *
104     *  @see Thread#Thread(ThreadGroup, Runnable, String, long, boolean)
105     */
106    public ThreadFactoryBuilder setInheritThreadLocals( final boolean flag );
107
108    /**
109     *  <p>{@summary Sets the flag whether the new thread created by the new
110     *  thread factory should be a daemon thread.} Daemon threads will be
111     *  aborted automatically when the last non-daemon thread terminates.</p>
112     *  <p>If not set, the new threads are not daemon threads.</p>
113     *
114     *  @param  flag    {@code true} if the new threads are daemon threads,
115     *      {@code false} if they are regular threads.
116     *  @return The builder.
117     *
118     *  @see Thread#isDaemon()
119     *  @see Thread#setDaemon(boolean)
120     */
121    public ThreadFactoryBuilder setDaemon( final boolean flag );
122
123    /**
124     *  <p>{@summary Sets the factory for the name of the threads created by
125     *  the new thread factory.}</p>
126     *  <p>The name factory method will be call with a numeric argument that is
127     *  unique for each invocation by the new thread factory; in fact, it is a
128     *  counter value.</p>
129     *  <p>If not set, a name factory is used that returns names looking like
130     *  this: &quot;{@code Thread-#}&quot; where the hash symbol will be
131     *  replaced by the counter value.</p>
132     *
133     *  @param  nameFactory The name factory.
134     *  @return The builder.
135     */
136    public ThreadFactoryBuilder setNameFactory( final IntFunction<String> nameFactory );
137
138    /**
139     *  <p>{@summary Sets the priority for the new threads created by the new
140     *  thread factory.} Proper values are -1 (to indicate that the priority
141     *  should not be set explicitly) and numbers between
142     *  {@value Thread#MIN_PRIORITY}
143     *  to
144     *  {@value Thread#MAX_PRIORITY},
145     *  inclusively.</p>
146     *  <p>If not set, the value will be -1.</p>
147     *  <p>If the thread factory will not be configured explicitly with a
148     *  priority, the newly created threads will get their priority set equal
149     *  to the priority of the thread calling
150     *  {@link ThreadFactory#newThread(Runnable)},
151     *  creating a new thread. The method
152     *  {@link Thread#setPriority(int)}
153     *  may be used to change the priority to a new value.</p>
154     *
155     *  @param  priority    The priority value.
156     *  @return The builder.
157     *  @throws ValidationException The given value is not valid.
158     *
159     *  @see Thread#setPriority(int)
160     */
161    public ThreadFactoryBuilder setPriority( final int priority ) throws ValidationException;
162
163    /**
164     *  <p>{@summary Sets the stack size for the new threads created by the new
165     *  thread factory.} The stack size is the approximate number of bytes of
166     *  address space that the virtual machine is to allocate for the new
167     *  thread's stack. The effect of the {@code stackSize} parameter, if any,
168     *  is highly platform dependent.</p>
169     *  <p>On some platforms, specifying a higher value for the
170     *  {@code stackSize} parameter may allow a thread to achieve greater
171     *  recursion depth before throwing a
172     *  {@link StackOverflowError}.
173     *  Similarly, specifying a lower value may allow a greater number of
174     *  threads to exist concurrently without throwing an
175     *  {@link OutOfMemoryError}
176     *  (or other internal error). The details of the relationship between the
177     *  value of the {@code stackSize} parameter and the maximum recursion
178     *  depth and concurrency level are platform-dependent. On some platforms,
179     *  the value of the {@code stackSize} parameter may have no effect
180     *  whatsoever.</p>
181     *  <p>The virtual machine is free to treat the stackSize parameter as a
182     *  suggestion. If the specified value is unreasonably low for the
183     *  platform, the virtual machine may instead use some platform-specific
184     *  minimum value; if the specified value is unreasonably high, the virtual
185     *  machine may instead use some platform-specific maximum. Likewise, the
186     *  virtual machine is free to round the specified value up or down as it
187     *  sees fit (or to ignore it completely).</p>
188     *  <p>Specifying a value of zero for the {@code stackSize} parameter will
189     *  cause the new tread factory to not set the stack size for the new
190     *  threads explicitly.</p>
191     *
192     *  @note Due to the platform-dependent nature of the behaviour regarding
193     *      this configuration value, extreme care should be exercised in its
194     *      use. The thread stack size necessary to perform a given computation
195     *      will likely vary from one JRE implementation to another. In light
196     *      of this variation, careful tuning of the stack size parameter may
197     *      be required, and the tuning may need to be repeated for each JRE
198     *      implementation on which an application is to run.
199     *
200     *  @param  stackSize   The stack size for the new threads.
201     *  @return The builder.
202     *
203     *  @see Thread#Thread(ThreadGroup, Runnable, String, long, boolean)
204     *  @see Thread#Thread(ThreadGroup, Runnable, String, long)
205     */
206    public ThreadFactoryBuilder setStackSize( final long stackSize );
207
208    /**
209     *  <p>{@summary Sets the thread group for the new threads created by the
210     *  new thread factory.}</p>
211     *  <p>If no thread group will be specified, the thread group for threads
212     *  created by the new thread factory is set to the thread group of the
213     *  thread that called .
214     *  {@link ThreadFactory#newThread(Runnable)}.</p>
215     *
216     *  @param  threadGroup The thread group.
217     *  @return The builder.
218     *
219     *  @see Thread#Thread(ThreadGroup, Runnable, String, long, boolean)
220     *  @see Thread#Thread(ThreadGroup, Runnable, String, long)
221     *  @see Thread#Thread(ThreadGroup, String)
222     *  @see Thread#Thread(ThreadGroup, Runnable)
223     *  @see Thread#Thread(ThreadGroup, Runnable, String)
224     */
225    public ThreadFactoryBuilder setThreadGroup( final ThreadGroup threadGroup );
226
227    /**
228     *  <p>{@summary Sets the
229     *  {@link java.lang.Thread.UncaughtExceptionHandler UncaughtExceptionHandler}
230     *  for the new threads created by the new thread factory.}</p>
231     *  <p>No handler will be set if none is specified for the new factory.</p>
232     *
233     *  @param  uncaughtExceptionHandler    The uncaught exception handler.
234     *  @return The builder.
235     *
236     *  @see Thread#setUncaughtExceptionHandler(UncaughtExceptionHandler)
237     *  @see Thread#setDefaultUncaughtExceptionHandler(UncaughtExceptionHandler)
238     *  @see Thread#getUncaughtExceptionHandler()
239     *  @see Thread#getDefaultUncaughtExceptionHandler()
240     *  @see ThreadGroup#uncaughtException(Thread, Throwable)
241     */
242    public ThreadFactoryBuilder setUncaughtExceptionHandler( final UncaughtExceptionHandler uncaughtExceptionHandler );
243
244    /**
245     *  Determines whether the threads generated by this thread factory will be
246     *  <i>virtual</i> threads.
247     *
248     *  @param  flag    {@code true} if the generated threads are virtual,
249     *      otherwise {@code false}.
250     *
251     *  @since 0.4.5
252     */
253    @API( status = STABLE, since = "0.4.5" )
254    public ThreadFactoryBuilder setVirtual( final boolean flag );
255}
256//  interface ThreadFactoryBuilder
257
258/*
259 *  End of File
260 */