1 /*
2 * Entreri, an entity-component framework in Java
3 *
4 * Copyright (c) 2013, Michael Ludwig
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without modification,
8 * are permitted provided that the following conditions are met:
9 *
10 * Redistributions of source code must retain the above copyright notice,
11 * this list of conditions and the following disclaimer.
12 * Redistributions in binary form must reproduce the above copyright notice,
13 * this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
20 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
23 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27 package com.lhkbob.entreri.task;
28
29 import com.lhkbob.entreri.EntitySystem;
30
31 /**
32 * <p/>
33 * Tasks are functional processors of the entities and components within an EntitySystem.
34 * Different Task implementations have different purposes, such as updating transforms,
35 * computing physics or AI, or rendering a scene. Generally task implementations should be
36 * as small and as independent as possible to allow for reuse and easy composability.
37 * <p/>
38 * The {@link Job} and {@link Scheduler} work together to coordinate the execution of
39 * collections of tasks. Tasks are grouped into jobs, where a job represents a logical
40 * step such as "render frame", or "compute physics", even if it is split into multiple
41 * tasks. Within a job, tasks are executed serially, but the scheduler can run different
42 * jobs simultaneously.
43 * <p/>
44 * The {@link ParallelAware} can be used with tasks to restrict the contention points of a
45 * job. This is important because a job acquires the locks for each of its tasks before
46 * invoking the first task. The locks are not released until the last task has
47 * terminated.
48 * <p/>
49 * A task can communicate with the remaining tasks of a job by {@link Job#report(Result)
50 * reporting} results. The results are only reported to tasks within the owning job, and
51 * that are executed after the current task. Thus tasks that have already completed their
52 * processing will not receive new results.
53 * <p/>
54 * A task receives results by defining any number of methods with the signature
55 * <code>public void report(T extends Result)</code>. When a result is reported to the
56 * job, it will invoke using reflection any <code>report()</code> method that takes a
57 * result of the compatible type.
58 * <p/>
59 * Task instances should only ever be used with a single job and entity system. If the
60 * task needs to be performed in multiple jobs or systems, new instances of the same type
61 * should be created.
62 *
63 * @author Michael Ludwig
64 */
65 public interface Task {
66 /**
67 * <p/>
68 * Invoke task specific operations to process the EntitySystem. This will be invoked
69 * on the task's parent job's thread, after the job has acquired any locks mandated by
70 * {@link ParallelAware}. If this task is not ParallelAware, the job acquires an
71 * exclusive lock with the assumption that it could modify anything.
72 * <p/>
73 * A task can return another task to be invoked after the owning job completes. These
74 * returned tasks are executed within their own set of locks, so it can be used to
75 * segment how long, and which locks are held by a job.
76 *
77 * @param system The EntitySystem being processed, which will always be the same for a
78 * given Task instance
79 * @param job The Job this task belongs to
80 *
81 * @return A nullable task that is executed after the job is completed
82 */
83 public Task process(EntitySystem system, Job job);
84
85 /**
86 * <p/>
87 * Reset any internal storage within this Task in preparation for the next execution
88 * of its owning job. This is used when jobs are scheduled to repeat at a given rate.
89 * Instead of instantiating new tasks every time, they can reset their tasks.
90 * <p/>
91 * Examples of how this can be used is if a spatial index is built up per-frame, or if
92 * decorated properties cache computed results. By using reset(), it's not necessary
93 * to re-decorate or allocate again.
94 *
95 * @param system The EntitySystem that will be processed, which will always be the
96 * same for a given Task instance
97 */
98 public void reset(EntitySystem system);
99 }