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.Component;
30 import com.lhkbob.entreri.Entity;
31 import com.lhkbob.entreri.EntitySystem;
32
33 import java.util.Set;
34
35 /**
36 * <p/>
37 * ParallelAware is an interface that {@link Task} implementations can implement. Tasks
38 * that are parallel aware hold to the contract that they will only modify a limited and
39 * knowable set of component types, or that they will or will not add or remove entities
40 * from the entity system.
41 * <p/>
42 * With that assumption based on the what is returned by {@link #getAccessedComponents()}
43 * and {@link #isEntitySetModified()}, jobs will automatically guarantee thread safe
44 * execution of their tasks.
45 * <p/>
46 * It is highly recommended to implement ParallelAware if it's known what types of
47 * components or entities will be modified at compile time.
48 *
49 * @author Michael Ludwig
50 */
51 public interface ParallelAware {
52 /**
53 * <p/>
54 * Get the set of all component data types that might have their data mutated, be
55 * added to, or removed from an entity. This must always return the same types for a
56 * given instance, it cannot change based on state of the task. Instead, it must
57 * return the maximal set of types that might be added, removed, or modified by the
58 * task.
59 * <p/>
60 * If a task's component access is determined at runtime, then it should not be
61 * parallel aware, or it should return true from {@link #isEntitySetModified()}.
62 * <p/>
63 * Jobs that do not share any access to the same component types (i.e. their
64 * intersection of the returned set is empty), can be run in parallel if they both
65 * return false from {@link #isEntitySetModified()}.
66 *
67 * @return The set of all component types that might be added, removed, or modified by
68 * the task
69 */
70 public Set<Class<? extends Component>> getAccessedComponents();
71
72 /**
73 * <p/>
74 * Return whether or not {@link Entity entities} are added or removed from an
75 * EntitySystem. Note that this refers to using {@link EntitySystem#addEntity()} or
76 * {@link EntitySystem#removeEntity(Entity)}. When true is returned, the job will be
77 * forced to execute with an exclusive lock that blocks other jobs.
78 * <p/>
79 * Thus it is a best practice to limit the run-time of tasks that require exclusive
80 * locks. It is better to have a parallel aware task that accesses only specific
81 * component types to determine if an entity must be added or removed.
82 * <p/>
83 * Once these are determined, it keeps track and returns a new task from {@link
84 * Task#process(EntitySystem, Job)} that will get the exclusive lock and perform the
85 * determined additions or removals.
86 * <p/>
87 * Like {@link #getAccessedComponents()}, this must always return the same value for a
88 * given instance, and cannot change during its lifetime.
89 *
90 * @return True if the task might add or remove entities from the system
91 */
92 public boolean isEntitySetModified();
93 }