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.EntitySystem;
31
32 import java.util.Collections;
33 import java.util.Set;
34
35 /**
36 * Timers is a utility class that provides factory methods for creating Tasks that report
37 * {@link ElapsedTimeResult} for use with other tasks that might have time-dependent
38 * behavior.
39 *
40 * @author Michael Ludwig
41 */
42 public final class Timers {
43 private Timers() {
44 }
45
46 /**
47 * <p/>
48 * Create a new Task that reports an {@link ElapsedTimeResult} with the provided fixed
49 * time delta. It is generally recommended for this task to be one of the first to
50 * execute within a job.
51 * <p/>
52 * The created task always reports the fixed time delta, regardless of true elapsed
53 * time between invocations, and performs no other action.
54 *
55 * @param dt The fixed time delta to always report
56 *
57 * @return Return a task that measures and reports a fixed delta
58 *
59 * @throws IllegalArgumentException if dt is less than or equal to zero
60 */
61 public static Task fixedDelta(double dt) {
62 if (dt <= 0) {
63 throw new IllegalArgumentException("Fixed delta must be positive: " + dt);
64 }
65 return new FixedDeltaTask(dt);
66 }
67
68 /**
69 * <p/>
70 * Create a new Task that reports an {@link ElapsedTimeResult} with the elapsed time
71 * since the start of the task's last invocation. It is generally recommended for this
72 * task to be one of the first to execute within a job.
73 * <p/>
74 * The created task always reports the measured elapsed time and performs no other
75 * action.
76 *
77 * @return Return a task that measures and reports delta time
78 */
79 public static Task measuredDelta() {
80 return new MeasuredDeltaTask();
81 }
82
83 /*
84 * Task that reports the same delta each invocation, even if it does equal
85 * the elapsed wall time
86 */
87 private static class FixedDeltaTask implements Task, ParallelAware {
88 private final ElapsedTimeResult delta;
89
90 public FixedDeltaTask(double dt) {
91 delta = new ElapsedTimeResult(dt);
92 }
93
94 @Override
95 public Task process(EntitySystem system, Job job) {
96 job.report(delta);
97 return null;
98 }
99
100 @Override
101 public void reset(EntitySystem system) {
102 // do nothing
103 }
104
105 @Override
106 public Set<Class<? extends Component>> getAccessedComponents() {
107 return Collections.emptySet();
108 }
109
110 @Override
111 public boolean isEntitySetModified() {
112 return false;
113 }
114 }
115
116 /*
117 * Task that measures the time delta from its last invocation
118 */
119 private static class MeasuredDeltaTask implements Task, ParallelAware {
120 private long lastStart = -1L;
121
122 @Override
123 public Task process(EntitySystem system, Job job) {
124 long now = System.nanoTime();
125 if (lastStart <= 0) {
126 job.report(new ElapsedTimeResult(0));
127 } else {
128 job.report(new ElapsedTimeResult((now - lastStart) / 1e9));
129 }
130 lastStart = now;
131
132 return null;
133 }
134
135 @Override
136 public void reset(EntitySystem system) {
137 // do nothing
138 }
139
140 @Override
141 public Set<Class<? extends Component>> getAccessedComponents() {
142 return Collections.emptySet();
143 }
144
145 @Override
146 public boolean isEntitySetModified() {
147 return false;
148 }
149 }
150 }