Skip to content

Commit 6763651

Browse files
committed
Added a system for running tasks once per frame until the task indicates
that it no longer wants to be run. This comes up a lot and I was tired of writing whole services just to get a once-per-frame update.
1 parent 5c7b073 commit 6763651

File tree

2 files changed

+117
-0
lines changed

2 files changed

+117
-0
lines changed

release-notes.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ Version 1.8.0 (unreleased)
1111
of an existing/custom GameSystemManager.
1212
* Added GameSystemsState.getGameSystemManager() and
1313
GameSystemsState.get(class, boolean) methods.
14+
* Added RecurringTaskSystem for executing general tasks once per frame.
1415

1516

1617
Version 1.7.0 (latest)
Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
/*
2+
* $Id$
3+
*
4+
* Copyright (c) 2022, Simsilica, LLC
5+
* All rights reserved.
6+
*
7+
* Redistribution and use in source and binary forms, with or without
8+
* modification, are permitted provided that the following conditions
9+
* are met:
10+
*
11+
* 1. Redistributions of source code must retain the above copyright
12+
* notice, this list of conditions and the following disclaimer.
13+
*
14+
* 2. Redistributions in binary form must reproduce the above copyright
15+
* notice, this list of conditions and the following disclaimer in
16+
* the documentation and/or other materials provided with the
17+
* distribution.
18+
*
19+
* 3. Neither the name of the copyright holder nor the names of its
20+
* contributors may be used to endorse or promote products derived
21+
* from this software without specific prior written permission.
22+
*
23+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24+
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25+
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
26+
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
27+
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
28+
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29+
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
30+
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31+
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
32+
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
33+
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
34+
* OF THE POSSIBILITY OF SUCH DAMAGE.
35+
*/
36+
37+
package com.simsilica.sim;
38+
39+
import java.util.*;
40+
import java.util.function.Function;
41+
42+
import org.slf4j.*;
43+
44+
/**
45+
* A GameSystem that supports recurring tasks.
46+
*
47+
* @author Paul Speed
48+
*/
49+
public class RecurringTaskSystem extends AbstractGameSystem {
50+
51+
static Logger log = LoggerFactory.getLogger(RecurringTaskSystem.class);
52+
53+
private List<Function<SimTime, Boolean>> tasks = new ArrayList<>();
54+
private volatile Function[] taskArray;
55+
private static Function[] EMPTY_ARRAY = new Function[0];
56+
57+
public RecurringTaskSystem() {
58+
}
59+
60+
/**
61+
* Adds a recurring task that will continue to run once a frame
62+
* as long as it returns Boolean.TRUE.
63+
*/
64+
public void addRecurringTask( Function<SimTime, Boolean> task ) {
65+
synchronized(tasks) {
66+
tasks.add(task);
67+
taskArray = null;
68+
}
69+
}
70+
71+
public void removeRecurringTask( Function<SimTime, Boolean> task ) {
72+
synchronized(tasks) {
73+
tasks.remove(task);
74+
taskArray = null;
75+
}
76+
}
77+
78+
protected Function[] getArray() {
79+
// Grab the array, unprotected, so it doesn't move underneath us
80+
Function[] result = taskArray;
81+
if( result != null ) {
82+
return result;
83+
}
84+
85+
// Else a little double-checked locking
86+
synchronized(tasks) {
87+
// See if one was created in the mean time
88+
if( taskArray != null ) {
89+
return taskArray;
90+
}
91+
taskArray = tasks.toArray(EMPTY_ARRAY);
92+
return taskArray;
93+
}
94+
}
95+
96+
@Override
97+
@SuppressWarnings("unchecked")
98+
public void update( SimTime time ) {
99+
for( Function f : getArray() ) {
100+
Object result = f.apply(time);
101+
if( !Objects.equals(result, Boolean.TRUE) ) {
102+
removeRecurringTask((Function<SimTime, Boolean>)f);
103+
}
104+
}
105+
}
106+
107+
@Override
108+
protected void initialize() {
109+
}
110+
111+
@Override
112+
protected void terminate() {
113+
}
114+
}
115+
116+

0 commit comments

Comments
 (0)