* fix for issue #1178 (BulletAppState violates AppState contract) * BulletAppState: make isRunning volatile (potential multithreaded access)
This commit is contained in:
parent
dcb66977ba
commit
0425c61dd4
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2009-2018 jMonkeyEngine
|
* Copyright (c) 2009-2019 jMonkeyEngine
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
@ -32,7 +32,7 @@
|
|||||||
package com.jme3.bullet;
|
package com.jme3.bullet;
|
||||||
|
|
||||||
import com.jme3.app.Application;
|
import com.jme3.app.Application;
|
||||||
import com.jme3.app.state.AppState;
|
import com.jme3.app.state.AbstractAppState;
|
||||||
import com.jme3.app.state.AppStateManager;
|
import com.jme3.app.state.AppStateManager;
|
||||||
import com.jme3.bullet.PhysicsSpace.BroadphaseType;
|
import com.jme3.bullet.PhysicsSpace.BroadphaseType;
|
||||||
import com.jme3.bullet.debug.BulletDebugAppState;
|
import com.jme3.bullet.debug.BulletDebugAppState;
|
||||||
@ -49,27 +49,16 @@ import java.util.logging.Logger;
|
|||||||
*
|
*
|
||||||
* @author normenhansen
|
* @author normenhansen
|
||||||
*/
|
*/
|
||||||
public class BulletAppState implements AppState, PhysicsTickListener {
|
public class BulletAppState
|
||||||
|
extends AbstractAppState
|
||||||
// FIXME: the bullet app state doesn't follow the proper AppState
|
implements PhysicsTickListener {
|
||||||
// contract as it messes with its initialized state independently
|
|
||||||
// of when initialize()/cleanup() is actually called. This means
|
|
||||||
// that it's quite likely that the state manager will think the
|
|
||||||
// app state is initialized when it, itself, doesn't. This is
|
|
||||||
// a good example of why extending the abstract app state classes
|
|
||||||
// is better than implementing app state directly. If it wants
|
|
||||||
// to support a separate stated/not-started concept then that's
|
|
||||||
// separate from initialized/not-initialized but way more refactoring
|
|
||||||
// than I want to think about today. -pspeed:2019-09-15
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* true if-and-only-if the physics simulation is running (started but not
|
* true if-and-only-if the physics simulation is running (started but not
|
||||||
* yet stopped)
|
* yet stopped)
|
||||||
*/
|
*/
|
||||||
protected boolean initialized = false;
|
protected volatile boolean isRunning = false;
|
||||||
protected Application app;
|
protected Application app;
|
||||||
private String id;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* manager that manages this state, set during attach
|
* manager that manages this state, set during attach
|
||||||
*/
|
*/
|
||||||
@ -245,7 +234,7 @@ public class BulletAppState implements AppState, PhysicsTickListener {
|
|||||||
* sooner, invoke this method.
|
* sooner, invoke this method.
|
||||||
*/
|
*/
|
||||||
public void startPhysics() {
|
public void startPhysics() {
|
||||||
if (initialized) {
|
if (isRunning) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -265,14 +254,14 @@ public class BulletAppState implements AppState, PhysicsTickListener {
|
|||||||
throw new IllegalStateException(threadingType.toString());
|
throw new IllegalStateException(threadingType.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
initialized = true;
|
isRunning = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Stop physics after this state is detached.
|
* Stop physics after this state is detached.
|
||||||
*/
|
*/
|
||||||
public void stopPhysics() {
|
public void stopPhysics() {
|
||||||
if(!initialized){
|
if (!isRunning) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (executor != null) {
|
if (executor != null) {
|
||||||
@ -281,7 +270,7 @@ public class BulletAppState implements AppState, PhysicsTickListener {
|
|||||||
}
|
}
|
||||||
pSpace.removeTickListener(this);
|
pSpace.removeTickListener(this);
|
||||||
pSpace.destroy();
|
pSpace.destroy();
|
||||||
initialized = false;
|
isRunning = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -291,54 +280,14 @@ public class BulletAppState implements AppState, PhysicsTickListener {
|
|||||||
* @param stateManager the manager for this state (not null)
|
* @param stateManager the manager for this state (not null)
|
||||||
* @param app the application which owns this state (not null)
|
* @param app the application which owns this state (not null)
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public void initialize(AppStateManager stateManager, Application app) {
|
public void initialize(AppStateManager stateManager, Application app) {
|
||||||
|
super.initialize(stateManager, app);
|
||||||
this.app = app;
|
this.app = app;
|
||||||
this.stateManager = stateManager;
|
this.stateManager = stateManager;
|
||||||
startPhysics();
|
startPhysics();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Test whether the physics simulation is running (started but not yet
|
|
||||||
* stopped).
|
|
||||||
*
|
|
||||||
* @return true if running, otherwise false
|
|
||||||
*/
|
|
||||||
public boolean isInitialized() {
|
|
||||||
return initialized;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the unique ID of this app state. Note: that setting
|
|
||||||
* this while an app state is attached to the state manager will
|
|
||||||
* have no effect on ID-based lookups.
|
|
||||||
*/
|
|
||||||
protected void setId( String id ) {
|
|
||||||
this.id = id;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getId() {
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Enable or disable this state.
|
|
||||||
*
|
|
||||||
* @param enabled true → enable, false → disable
|
|
||||||
*/
|
|
||||||
public void setEnabled(boolean enabled) {
|
|
||||||
this.active = enabled;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test whether this state is enabled.
|
|
||||||
*
|
|
||||||
* @return true if enabled, otherwise false
|
|
||||||
*/
|
|
||||||
public boolean isEnabled() {
|
|
||||||
return active;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Alter whether debug visualization is enabled.
|
* Alter whether debug visualization is enabled.
|
||||||
*
|
*
|
||||||
@ -364,8 +313,10 @@ public class BulletAppState implements AppState, PhysicsTickListener {
|
|||||||
*
|
*
|
||||||
* @param stateManager (not null)
|
* @param stateManager (not null)
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public void stateAttached(AppStateManager stateManager) {
|
public void stateAttached(AppStateManager stateManager) {
|
||||||
if (!initialized) {
|
super.stateAttached(stateManager);
|
||||||
|
if (!isRunning) {
|
||||||
startPhysics();
|
startPhysics();
|
||||||
}
|
}
|
||||||
if (threadingType == ThreadingType.PARALLEL) {
|
if (threadingType == ThreadingType.PARALLEL) {
|
||||||
@ -377,15 +328,6 @@ public class BulletAppState implements AppState, PhysicsTickListener {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Transition this state from running to terminating. Should be invoked only
|
|
||||||
* by a subclass or by the AppStateManager.
|
|
||||||
*
|
|
||||||
* @param stateManager (not null)
|
|
||||||
*/
|
|
||||||
public void stateDetached(AppStateManager stateManager) {
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update this state prior to rendering. Should be invoked only by a
|
* Update this state prior to rendering. Should be invoked only by a
|
||||||
* subclass or by the AppStateManager. Invoked once per frame, provided the
|
* subclass or by the AppStateManager. Invoked once per frame, provided the
|
||||||
@ -393,7 +335,9 @@ public class BulletAppState implements AppState, PhysicsTickListener {
|
|||||||
*
|
*
|
||||||
* @param tpf the time interval between frames (in seconds, ≥0)
|
* @param tpf the time interval between frames (in seconds, ≥0)
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public void update(float tpf) {
|
public void update(float tpf) {
|
||||||
|
super.update(tpf);
|
||||||
if (debugEnabled && debugAppState == null && pSpace != null) {
|
if (debugEnabled && debugAppState == null && pSpace != null) {
|
||||||
debugAppState = new BulletDebugAppState(pSpace);
|
debugAppState = new BulletDebugAppState(pSpace);
|
||||||
stateManager.attach(debugAppState);
|
stateManager.attach(debugAppState);
|
||||||
@ -415,7 +359,9 @@ public class BulletAppState implements AppState, PhysicsTickListener {
|
|||||||
*
|
*
|
||||||
* @param rm the render manager (not null)
|
* @param rm the render manager (not null)
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public void render(RenderManager rm) {
|
public void render(RenderManager rm) {
|
||||||
|
super.render(rm);
|
||||||
if (!active) {
|
if (!active) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -432,7 +378,9 @@ public class BulletAppState implements AppState, PhysicsTickListener {
|
|||||||
* invoked only by a subclass or by the AppStateManager. Invoked once per
|
* invoked only by a subclass or by the AppStateManager. Invoked once per
|
||||||
* frame, provided the state is attached and enabled.
|
* frame, provided the state is attached and enabled.
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public void postRender() {
|
public void postRender() {
|
||||||
|
super.postRender();
|
||||||
if (physicsFuture != null) {
|
if (physicsFuture != null) {
|
||||||
try {
|
try {
|
||||||
physicsFuture.get();
|
physicsFuture.get();
|
||||||
@ -451,12 +399,14 @@ public class BulletAppState implements AppState, PhysicsTickListener {
|
|||||||
* {@link #initialize(com.jme3.app.state.AppStateManager, com.jme3.app.Application)}
|
* {@link #initialize(com.jme3.app.state.AppStateManager, com.jme3.app.Application)}
|
||||||
* is invoked.
|
* is invoked.
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public void cleanup() {
|
public void cleanup() {
|
||||||
if (debugAppState != null) {
|
if (debugAppState != null) {
|
||||||
stateManager.detach(debugAppState);
|
stateManager.detach(debugAppState);
|
||||||
debugAppState = null;
|
debugAppState = null;
|
||||||
}
|
}
|
||||||
stopPhysics();
|
stopPhysics();
|
||||||
|
super.cleanup();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Loading…
x
Reference in New Issue
Block a user