View Javadoc

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  }