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 }