jaulib v1.3.0
Jau Support Library (C++, Java, ..)
FunctionTask.java
Go to the documentation of this file.
1/**
2 * Author: Sven Gothel <sgothel@jausoft.com>
3 * Copyright (c) 2021 Gothel Software e.K.
4 * Copyright (c) 2013 Gothel Software e.K.
5 * Copyright (c) 2013 JogAmp Community.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining
8 * a copy of this software and associated documentation files (the
9 * "Software"), to deal in the Software without restriction, including
10 * without limitation the rights to use, copy, modify, merge, publish,
11 * distribute, sublicense, and/or sell copies of the Software, and to
12 * permit persons to whom the Software is furnished to do so, subject to
13 * the following conditions:
14 *
15 * The above copyright notice and this permission notice shall be
16 * included in all copies or substantial portions of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
22 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
23 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
24 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 */
26
27package org.jau.util.parallel;
28
29import java.io.PrintStream;
30
31import org.jau.lang.InterruptSource;
32import org.jau.lang.InterruptedRuntimeException;
33import org.jau.util.Function;
34
35/**
36 * Helper class to provide a Runnable queue implementation with a Runnable wrapper
37 * which notifies after execution for the <code>invokeAndWait()</code> semantics.
38 */
39public class FunctionTask<R,A> extends TaskBase implements Function<R,A> {
41 protected R result;
42 protected A[] args;
43
44 /**
45 * Invokes <code>func</code> on the current {@link Thread}.
46 * <p>
47 * The result can be retrieved via {@link FunctionTask#getResult()},
48 * using the returned instance.
49 * </p>
50 * @param func the {@link Function} to execute.
51 * @param args the {@link Function} arguments
52 * @return the newly created and invoked {@link FunctionTask}
53 * @since 0.3.0
54 */
55 @SafeVarargs
56 public static <U,V> FunctionTask<U,V> invokeOnCurrentThread(final Function<U,V> func, final V... args) {
57 final FunctionTask<U,V> rt = new FunctionTask<U,V>( func, null, false, null);
58 rt.args = args;
59 rt.run();
60 return rt;
61 }
62
63 /**
64 * Invokes <code>func</code> on a new {@link InterruptSource.Thread},
65 * see {@link InterruptSource.Thread#Thread(ThreadGroup, Runnable, String)} for details.
66 * <p>
67 * The result can be retrieved via {@link FunctionTask#getResult()},
68 * using the returned instance.
69 * </p>
70 * @param tg the {@link ThreadGroup} for the new thread, maybe <code>null</code>
71 * @param threadName the name for the new thread, maybe <code>null</code>
72 * @param waitUntilDone if <code>true</code>, waits until <code>func</code> execution is completed, otherwise returns immediately.
73 * @param func the {@link Function} to execute.
74 * @param args the {@link Function} arguments
75 * @return the newly created and invoked {@link FunctionTask}
76 * @since 0.3.0
77 */
78 @SafeVarargs
79 public static <U,V> FunctionTask<U,V> invokeOnNewThread(final ThreadGroup tg, final String threadName,
80 final boolean waitUntilDone, final Function<U,V> func, final V... args) {
81 final FunctionTask<U,V> rt;
82 if( !waitUntilDone ) {
83 rt = new FunctionTask<U,V>( func, null, true, System.err );
84 final InterruptSource.Thread t = InterruptSource.Thread.create(tg, rt, threadName);
85 rt.args = args;
86 t.start();
87 } else {
88 final Object sync = new Object();
89 rt = new FunctionTask<U,V>( func, sync, true, null );
90 final InterruptSource.Thread t = InterruptSource.Thread.create(tg, rt, threadName);
91 synchronized(sync) {
92 rt.args = args;
93 t.start();
94 while( rt.isInQueue() ) {
95 try {
96 sync.wait();
97 } catch (final InterruptedException ie) {
98 throw new InterruptedRuntimeException(ie);
99 }
100 final Throwable throwable = rt.getThrowable();
101 if(null!=throwable) {
102 throw new RuntimeException(throwable);
103 }
104 }
105 }
106 }
107 return rt;
108 }
109
110 /**
111 * Create a RunnableTask object w/ synchronization,
112 * ie. suitable for <code>invokeAndWait()</code>.
113 *
114 * @param runnable the user action
115 * @param syncObject the synchronization object the caller shall wait until <code>runnable</code> execution is completed,
116 * or <code>null</code> if waiting is not desired.
117 * @param catchExceptions Influence an occurring exception during <code>runnable</code> execution.
118 * If <code>true</code>, the exception is silenced and can be retrieved via {@link #getThrowable()},
119 * otherwise the exception is thrown.
120 * @param exceptionOut If not <code>null</code>, exceptions are written to this {@link PrintStream}.
121 */
122 public FunctionTask(final Function<R,A> runnable, final Object syncObject, final boolean catchExceptions, final PrintStream exceptionOut) {
124 this.runnable = runnable ;
125 result = null;
126 args = null;
127 }
128
129 /** Return the user action */
130 public final Function<R,A> getRunnable() {
131 return runnable;
132 }
133
134 /**
135 * Sets the arguments for {@link #run()}.
136 * They will be cleared after calling {@link #run()} or {@link #eval(Object...)}.
137 */
138 @SafeVarargs
139 public final void setArgs(final A... args) {
140 this.args = args;
141 }
142
143 /**
144 * Retrieves the cached result of {@link #run()}
145 * and is cleared within this method.
146 */
147 public final R getResult() {
148 final R res = result;
149 result = null;
150 return res;
151 }
152
153 /**
154 * {@inheritDoc}
155 * <p>
156 * Calls {@link #eval(Object...)}.
157 * </p>
158 * <p>
159 * You may set the {@link #eval(Object...)} arguments via {@link #setArgs(Object...)}
160 * and retrieve the result via {@link #getResult()}.
161 * </p>
162 */
163 @Override
164 public final void run() {
165 execThread = Thread.currentThread();
166
167 final A[] args = this.args;
168 this.args = null;
169 this.result = null;
170 runnableException = null;
171 tStarted = System.currentTimeMillis();
172 if(null == syncObject) {
173 try {
174 this.result = runnable.eval(args);
175 } catch (final Throwable t) {
177 if(null != exceptionOut) {
178 exceptionOut.println("FunctionTask.run(): "+getExceptionOutIntro()+" exception occured on thread "+Thread.currentThread().getName()+": "+toString());
180 t.printStackTrace(exceptionOut);
181 }
182 if(!catchExceptions) {
183 throw new RuntimeException(runnableException);
184 }
185 } finally {
186 tExecuted = System.currentTimeMillis();
187 isExecuted = true;
188 }
189 } else {
190 synchronized (syncObject) {
191 try {
192 this.result = runnable.eval(args);
193 } catch (final Throwable t) {
195 if(null != exceptionOut) {
196 exceptionOut.println("FunctionTask.run(): "+getExceptionOutIntro()+" exception occured on thread "+Thread.currentThread().getName()+": "+toString());
198 t.printStackTrace(exceptionOut);
199 }
200 if(!catchExceptions) {
201 throw new RuntimeException(runnableException);
202 }
203 } finally {
204 tExecuted = System.currentTimeMillis();
205 isExecuted = true;
206 syncObject.notifyAll();
207 }
208 }
209 }
210 }
211
212 @Override
213 @SafeVarargs
214 public final R eval(final A... args) {
215 this.args = args;
216 run();
217 final R res = result;
218 result = null;
219 return res;
220 }
221}
222
java.lang.Thread specialization implementing InterruptSource to track java.lang.Thread#interrupt() ca...
static Thread create(final ThreadGroup tg, final Runnable target, final String name)
Depending on whether name is null, either Thread(ThreadGroup, Runnable, String) or Thread(ThreadGroup...
Unchecked exception propagating an InterruptedException where handling of the latter is not desired.
Helper class to provide a Runnable queue implementation with a Runnable wrapper which notifies after ...
static< U, V > FunctionTask< U, V > invokeOnNewThread(final ThreadGroup tg, final String threadName, final boolean waitUntilDone, final Function< U, V > func, final V... args)
Invokes func on a new InterruptSource.Thread, see InterruptSource.Thread#Thread(ThreadGroup,...
FunctionTask(final Function< R, A > runnable, final Object syncObject, final boolean catchExceptions, final PrintStream exceptionOut)
Create a RunnableTask object w/ synchronization, ie.
final void setArgs(final A... args)
Sets the arguments for run().
static< U, V > FunctionTask< U, V > invokeOnCurrentThread(final Function< U, V > func, final V... args)
Invokes func on the current Thread.
final R eval(final A... args)
Implementation may compute variable args list and returns a result.
final Function< R, A > getRunnable()
Return the user action.
final R getResult()
Retrieves the cached result of run() and is cleared within this method.
Helper class to provide a Runnable queue implementation with a Runnable wrapper which notifies after ...
Definition: TaskBase.java:38
final Throwable getThrowable()
Definition: TaskBase.java:170
final String getExceptionOutIntro()
Definition: TaskBase.java:81
volatile Thread execThread
Definition: TaskBase.java:58
volatile boolean isExecuted
Definition: TaskBase.java:56
final PrintStream exceptionOut
Definition: TaskBase.java:49
Interface exposing java.lang.Thread#interrupt() source, intended for java.lang.Thread specializations...
Generic function interface to perform an action w/ given optional arguments producing an optional res...
Definition: Function.java:38