Part 2 of the small AppState refactoring: added methods to AppStateManager
for retrieving an AppState by ID. Also modified attach() to throw an IllegalArgumentException if the ID is already registered. Updated TestAppStateLifeCycle to add a small ID demonstration.
This commit is contained in:
parent
3dd2755c20
commit
36afe829c6
@ -37,6 +37,8 @@ import com.jme3.renderer.RenderManager;
|
|||||||
import com.jme3.util.SafeArrayList;
|
import com.jme3.util.SafeArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.concurrent.ConcurrentMap;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The <code>AppStateManager</code> holds a list of {@link AppState}s which
|
* The <code>AppStateManager</code> holds a list of {@link AppState}s which
|
||||||
@ -83,6 +85,12 @@ public class AppStateManager {
|
|||||||
*/
|
*/
|
||||||
private final SafeArrayList<AppState> terminating = new SafeArrayList<AppState>(AppState.class);
|
private final SafeArrayList<AppState> terminating = new SafeArrayList<AppState>(AppState.class);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Thread-safe index of every state that is currently attached and has
|
||||||
|
* an ID.
|
||||||
|
*/
|
||||||
|
private final ConcurrentMap<String, AppState> stateIndex = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
// All of the above lists need to be thread safe but access will be
|
// All of the above lists need to be thread safe but access will be
|
||||||
// synchronized separately.... but always on the states list. This
|
// synchronized separately.... but always on the states list. This
|
||||||
// is to avoid deadlocking that may occur and the most common use case
|
// is to avoid deadlocking that may occur and the most common use case
|
||||||
@ -122,7 +130,8 @@ public class AppStateManager {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Attach a state to the AppStateManager, the same state cannot be attached
|
* Attach a state to the AppStateManager, the same state cannot be attached
|
||||||
* twice.
|
* twice. Throws an IllegalArgumentException if the state has an ID and that
|
||||||
|
* ID has already been associated with another AppState.
|
||||||
*
|
*
|
||||||
* @param state The state to attach
|
* @param state The state to attach
|
||||||
* @return True if the state was successfully attached, false if the state
|
* @return True if the state was successfully attached, false if the state
|
||||||
@ -130,6 +139,11 @@ public class AppStateManager {
|
|||||||
*/
|
*/
|
||||||
public boolean attach(AppState state){
|
public boolean attach(AppState state){
|
||||||
synchronized (states){
|
synchronized (states){
|
||||||
|
if( state.getId() != null && stateIndex.putIfAbsent(state.getId(), state) != null ) {
|
||||||
|
throw new IllegalArgumentException("ID:" + state.getId()
|
||||||
|
+ " is already being used by another state:"
|
||||||
|
+ stateIndex.get(state.getId()));
|
||||||
|
}
|
||||||
if (!states.contains(state) && !initializing.contains(state)){
|
if (!states.contains(state) && !initializing.contains(state)){
|
||||||
state.stateAttached(this);
|
state.stateAttached(this);
|
||||||
initializing.add(state);
|
initializing.add(state);
|
||||||
@ -175,6 +189,12 @@ public class AppStateManager {
|
|||||||
*/
|
*/
|
||||||
public boolean detach(AppState state){
|
public boolean detach(AppState state){
|
||||||
synchronized (states){
|
synchronized (states){
|
||||||
|
|
||||||
|
// Remove it from the index if it exists.
|
||||||
|
// Note: we remove it directly from the values() in case
|
||||||
|
// the state has changed its ID since registered.
|
||||||
|
stateIndex.values().remove(state);
|
||||||
|
|
||||||
if (states.contains(state)){
|
if (states.contains(state)){
|
||||||
state.stateDetached(this);
|
state.stateDetached(this);
|
||||||
states.remove(state);
|
states.remove(state);
|
||||||
@ -249,6 +269,35 @@ public class AppStateManager {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the state associated with the specified ID at the time it was
|
||||||
|
* attached or null if not state was attached with that ID.
|
||||||
|
*/
|
||||||
|
public <T extends AppState> T getState( String id, Class<T> stateClass ) {
|
||||||
|
return stateClass.cast(stateIndex.get(id));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if there is currently a state associated with the specified
|
||||||
|
* ID.
|
||||||
|
*/
|
||||||
|
public boolean hasState( String id ) {
|
||||||
|
return stateIndex.containsKey(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the state associated with the specified ID at the time it
|
||||||
|
* was attached or throws an IllegalArgumentException if the ID was
|
||||||
|
* not found.
|
||||||
|
*/
|
||||||
|
public <T extends AppState> T stateForId( String id, Class<T> stateClass ) {
|
||||||
|
T result = getState(id, stateClass);
|
||||||
|
if( result == null ) {
|
||||||
|
throw new IllegalArgumentException("State not found for:" + id);
|
||||||
|
}
|
||||||
|
return stateClass.cast(result);
|
||||||
|
}
|
||||||
|
|
||||||
protected void initializePending(){
|
protected void initializePending(){
|
||||||
AppState[] array = getInitializing();
|
AppState[] array = getInitializing();
|
||||||
if (array.length == 0)
|
if (array.length == 0)
|
||||||
|
@ -65,6 +65,9 @@ public class TestAppStateLifeCycle extends SimpleApplication {
|
|||||||
|
|
||||||
System.out.println("Attaching test state.");
|
System.out.println("Attaching test state.");
|
||||||
stateManager.attach(new TestState());
|
stateManager.attach(new TestState());
|
||||||
|
|
||||||
|
System.out.println("Attaching test state with an ID.");
|
||||||
|
stateManager.attach(new TestState("Test ID"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -75,50 +78,63 @@ public class TestAppStateLifeCycle extends SimpleApplication {
|
|||||||
stateManager.detach(stateManager.getState(TestState.class));
|
stateManager.detach(stateManager.getState(TestState.class));
|
||||||
System.out.println("Done");
|
System.out.println("Done");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if( stateManager.hasState("Test ID") ) {
|
||||||
|
System.out.println("Detaching test state with an ID.");
|
||||||
|
stateManager.detach(stateManager.getState("Test ID", TestState.class));
|
||||||
|
System.out.println("Done");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class TestState extends AbstractAppState {
|
public class TestState extends AbstractAppState {
|
||||||
|
|
||||||
|
public TestState() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public TestState( String id ) {
|
||||||
|
super(id);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void initialize(AppStateManager stateManager, Application app) {
|
public void initialize(AppStateManager stateManager, Application app) {
|
||||||
super.initialize(stateManager, app);
|
super.initialize(stateManager, app);
|
||||||
System.out.println("Initialized");
|
System.out.println("Initialized, id:" + getId());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void stateAttached(AppStateManager stateManager) {
|
public void stateAttached(AppStateManager stateManager) {
|
||||||
super.stateAttached(stateManager);
|
super.stateAttached(stateManager);
|
||||||
System.out.println("Attached");
|
System.out.println("Attached, id:" + getId());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void update(float tpf) {
|
public void update(float tpf) {
|
||||||
super.update(tpf);
|
super.update(tpf);
|
||||||
System.out.println("update");
|
System.out.println("update, id:" + getId());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void render(RenderManager rm) {
|
public void render(RenderManager rm) {
|
||||||
super.render(rm);
|
super.render(rm);
|
||||||
System.out.println("render");
|
System.out.println("render, id:" + getId());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void postRender() {
|
public void postRender() {
|
||||||
super.postRender();
|
super.postRender();
|
||||||
System.out.println("postRender");
|
System.out.println("postRender, id:" + getId());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void stateDetached(AppStateManager stateManager) {
|
public void stateDetached(AppStateManager stateManager) {
|
||||||
super.stateDetached(stateManager);
|
super.stateDetached(stateManager);
|
||||||
System.out.println("Detached");
|
System.out.println("Detached, id:" + getId());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void cleanup() {
|
public void cleanup() {
|
||||||
super.cleanup();
|
super.cleanup();
|
||||||
System.out.println("Cleanup");
|
System.out.println("Cleanup, id:" + getId());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user