summaryrefslogtreecommitdiff
path: root/base/src/main/java/bjc/utils/funcutils/Strategy.java
blob: 316879f223b7a1030c6bf7203631aa400ee89fed (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
package bjc.utils.funcutils;

import java.util.concurrent.*;
import java.util.function.*;

/**
 * Strategy for dealing with parallel execution.
 * 
 * @author Ben Culkin
 * 
 * @param <Output> The type returned by the tasks.
 *
 */
public interface Strategy<Output> extends Function<Callable<Output>, Future<Output>>
{
	/**
	 * Convert a function into one which operates concurrently, using this strategy.
	 * 
	 * @param <Input> The type of the function argument.
	 * 
	 * @param func The type of the function.
	 * 
	 * @return A function which executes concurrently.
	 */
	public default <Input> Function<Input, Future<Output>> using(Function<Input, Output> func)
	{
		return (input) -> this.apply(() -> func.apply(input));
	}
	
	/**
	 * A strategy which will run tasks in serial.
	 * 
	 * @param <Output> The type returned by the task.
	 * 
	 * @return A strategy which executes things serially.
	 */
	public static <Output> Strategy<Output> serial()
	{
		return (call) -> {
			FutureTask<Output> task = new FutureTask<>(call);
			task.run();
			return task;
		};
	}
	/**
	 * A strategy which creates a fresh thread to execute a task on.
	 * 
	 * @param <Output> The type returned by the task.
	 * 
	 * @return A strategy which uses threads to create tasks.
	 */
	public static <Output> Strategy<Output> simpleThread()
	{
		// I leave this as an example as of what is possible with combinators.
		// return (call) -> invoke(introducing(
		// 		() -> new FutureTask<>(call),
		// 		(task, input) -> doWith(
		// 				(FutureTask<Output> tsk) ->
		// 					new Thread(task).start()).apply(task)
		// ));
		return (call) -> {
			FutureTask<Output> task = new FutureTask<>(call);
			new Thread(task).start();
			return task;
		};
	}
	
	/**
	 * A strategy that uses an executor service.
	 * 
	 * @param <Output> The type returned by the task.
	 * 
	 * @param svc The executor service to use.
	 * 
	 * @return A strategy which uses the provided executor.
	 */
	public static <Output> Strategy<Output> executorService(ExecutorService svc)
	{
		return svc::submit;
	}
}