From 284c53489b89a6e39027aeab27c258c8926f77f0 Mon Sep 17 00:00:00 2001 From: Starla Insigna Date: Mon, 23 Feb 2009 09:20:19 -0500 Subject: Engine: Added Event Thread cancellation --- src/com/fourisland/fourpuzzle/Display.java | 61 ++++++++++++---------- .../gamestate/mapview/MapViewGameState.java | 11 ++++ .../gamestate/mapview/event/EventCall.java | 18 +++++-- .../gamestate/mapview/event/EventHandler.java | 9 ++++ .../gamestate/mapview/event/SpecialEvent.java | 24 +++++++-- .../mapview/event/specialmove/MoveEventThread.java | 59 ++++++++++++++++----- .../fourpuzzle/window/MessageWindow.java | 14 +++-- 7 files changed, 145 insertions(+), 51 deletions(-) diff --git a/src/com/fourisland/fourpuzzle/Display.java b/src/com/fourisland/fourpuzzle/Display.java index a8c9a37..c8d17d9 100755 --- a/src/com/fourisland/fourpuzzle/Display.java +++ b/src/com/fourisland/fourpuzzle/Display.java @@ -198,47 +198,54 @@ public class Display { transitionRunning = true; transitionWait = new CountDownLatch(1); - transitionWait.await(); - Display.transition = null; + try { + transitionWait.await(); + } catch (InterruptedException ex) { + throw ex; + } finally { + Display.transition = null; - if (!startedTransition) - { - transitionRunning = false; + if (!startedTransition) + { + transitionRunning = false; + } } } private static Executor transitioner = Executors.newSingleThreadExecutor(); - public static void transition(final OutTransition out, final GameState gameState, final InTransition in, boolean thread) + public static void transition(final OutTransition out, final GameState gameState, final InTransition in, boolean thread) throws InterruptedException { - Runnable transitionCall = new Runnable() { - public void run() - { - try { - Display.transition(out); - Game.setGameState(gameState); - Display.transition(in); - } catch (InterruptedException ex) { - Thread.currentThread().interrupt(); - } catch (RuntimeException ex) - { - PuzzleApplication.INSTANCE.reportError(ex); - } catch (Error ex) - { - PuzzleApplication.INSTANCE.reportError(ex); - } - } - }; - if (thread) { + Runnable transitionCall = new Runnable() { + public void run() + { + try { + Display.transition(out); + Game.setGameState(gameState); + Display.transition(in); + } catch (InterruptedException ex) { + return; + } catch (RuntimeException ex) + { + PuzzleApplication.INSTANCE.reportError(ex); + } catch (Error ex) + { + PuzzleApplication.INSTANCE.reportError(ex); + } + } + }; + transitioner.execute(transitionCall); } else { - transitionCall.run(); + Display.transition(out); + Game.setGameState(gameState); + Display.transition(in); } } - public static void transition(TransitionPair trans, GameState gameState, boolean thread) + public static void transition(TransitionPair trans, GameState gameState, boolean thread) throws InterruptedException { transition(trans.getOutTransition(), gameState, trans.getInTransition(), thread); } diff --git a/src/com/fourisland/fourpuzzle/gamestate/mapview/MapViewGameState.java b/src/com/fourisland/fourpuzzle/gamestate/mapview/MapViewGameState.java index 68e611b..ccb1829 100755 --- a/src/com/fourisland/fourpuzzle/gamestate/mapview/MapViewGameState.java +++ b/src/com/fourisland/fourpuzzle/gamestate/mapview/MapViewGameState.java @@ -141,6 +141,17 @@ public class MapViewGameState implements GameState { } } } + } + } + + if (EventHandler.isRunningEvent()) + { + if ((key.getKey() == KeyEvent.VK_F11) && (PuzzleApplication.INSTANCE.getContext().getResourceMap().getBoolean("debugMode"))) + { + for (LayerEvent ev : currentMap.getEvents()) + { + ev.getCallback().cancel(); + } } } } diff --git a/src/com/fourisland/fourpuzzle/gamestate/mapview/event/EventCall.java b/src/com/fourisland/fourpuzzle/gamestate/mapview/event/EventCall.java index 7214528..c94fc80 100755 --- a/src/com/fourisland/fourpuzzle/gamestate/mapview/event/EventCall.java +++ b/src/com/fourisland/fourpuzzle/gamestate/mapview/event/EventCall.java @@ -22,20 +22,28 @@ public abstract class EventCall extends SpecialEvent { }; } - public abstract void run(); + public abstract void run() throws InterruptedException; - private Future isRunning = null; + private Future eventThread = null; public void activate(EventCallTime calltime) { - if ((isRunning == null) || (isRunning.isDone())) + if ((eventThread == null) || (eventThread.isDone())) { if (calltime == EventCallTime.ParallelProcess) { - isRunning = EventHandler.runParallel(this); + eventThread = EventHandler.runParallel(this); } else { - isRunning = EventHandler.runEvent(this); + eventThread = EventHandler.runEvent(this); } } } + public void cancel() + { + if ((eventThread != null) && (!eventThread.isDone())) + { + eventThread.cancel(true); + } + } + } diff --git a/src/com/fourisland/fourpuzzle/gamestate/mapview/event/EventHandler.java b/src/com/fourisland/fourpuzzle/gamestate/mapview/event/EventHandler.java index a8a626f..e24b79c 100755 --- a/src/com/fourisland/fourpuzzle/gamestate/mapview/event/EventHandler.java +++ b/src/com/fourisland/fourpuzzle/gamestate/mapview/event/EventHandler.java @@ -6,6 +6,7 @@ package com.fourisland.fourpuzzle.gamestate.mapview.event; import com.fourisland.fourpuzzle.PuzzleApplication; +import com.fourisland.fourpuzzle.gamestate.mapview.viewpoint.AutomaticViewpoint; import com.fourisland.fourpuzzle.util.ResourceNotFoundException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; @@ -51,6 +52,14 @@ public class EventHandler { try { callback.run(); + } catch (InterruptedException ex) { + /* Swallow the interrupt, as the interruption probably + * indicates that the event should be cancelled + * + * Also reset the viewpoint in case the viewpoint was + * fixed during the thread */ + + SpecialEvent.mapView.setViewpoint(new AutomaticViewpoint(SpecialEvent.mapView.getCurrentMap())); } catch (ResourceNotFoundException ex) { PuzzleApplication.INSTANCE.reportError(ex); diff --git a/src/com/fourisland/fourpuzzle/gamestate/mapview/event/SpecialEvent.java b/src/com/fourisland/fourpuzzle/gamestate/mapview/event/SpecialEvent.java index c3bec32..1a33158 100755 --- a/src/com/fourisland/fourpuzzle/gamestate/mapview/event/SpecialEvent.java +++ b/src/com/fourisland/fourpuzzle/gamestate/mapview/event/SpecialEvent.java @@ -282,18 +282,26 @@ public class SpecialEvent { mapView.setViewpoint(new MovingViewpoint(viewpoint.getX(), viewpoint.getY(), x*16, y*16, new Runnable() { public void run() { - mapView.setViewpoint(new FixedViewpoint(x*16,y*16)); - if (block) { blocker.countDown(); + } else { + mapView.setViewpoint(new FixedViewpoint(x*16,y*16)); } } }, length)); if (block) { - blocker.await(); + try + { + blocker.await(); + } catch (InterruptedException ex) + { + throw ex; + } finally { + mapView.setViewpoint(new FixedViewpoint(x*16,y*16)); + } } } @@ -334,4 +342,14 @@ public class SpecialEvent { Audio.stopMusic(); } + /** + * Ends the currently executing event thread + * + * @throws InterruptedException + */ + public void StopThread() throws InterruptedException + { + throw new InterruptedException(); + } + } diff --git a/src/com/fourisland/fourpuzzle/gamestate/mapview/event/specialmove/MoveEventThread.java b/src/com/fourisland/fourpuzzle/gamestate/mapview/event/specialmove/MoveEventThread.java index 488331a..233c415 100755 --- a/src/com/fourisland/fourpuzzle/gamestate/mapview/event/specialmove/MoveEventThread.java +++ b/src/com/fourisland/fourpuzzle/gamestate/mapview/event/specialmove/MoveEventThread.java @@ -8,10 +8,12 @@ package com.fourisland.fourpuzzle.gamestate.mapview.event.specialmove; import com.fourisland.fourpuzzle.Game; import com.fourisland.fourpuzzle.gamestate.mapview.event.Event; import com.fourisland.fourpuzzle.gamestate.mapview.event.LayerEvent; +import java.util.ArrayList; import java.util.List; import java.util.Vector; -import java.util.concurrent.Executor; +import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; +import java.util.concurrent.Future; import java.util.concurrent.Semaphore; /** @@ -20,10 +22,11 @@ import java.util.concurrent.Semaphore; */ public class MoveEventThread implements Runnable { - private static Executor moveEventExecutor = Executors.newCachedThreadPool(); + private static ExecutorService moveEventExecutor = Executors.newCachedThreadPool(); private static volatile List events = new Vector(); private static volatile Semaphore moveEventWait = new Semaphore(100); + private static volatile List eventThreads = new ArrayList(); private Event ev; private MoveEvent[] actions; @@ -36,7 +39,15 @@ public class MoveEventThread implements Runnable { public void start() { - moveEventExecutor.execute(this); + for (Future f : eventThreads) + { + if (f.isDone()) + { + eventThreads.remove(f); + } + } + + eventThreads.add(moveEventExecutor.submit(this)); } public void run() @@ -44,7 +55,7 @@ public class MoveEventThread implements Runnable { try { moveEventWait.acquire(); } catch (InterruptedException ex) { - Thread.currentThread().interrupt(); + return; } while (ev.isMoving()) @@ -52,25 +63,49 @@ public class MoveEventThread implements Runnable { try { Thread.sleep(2); } catch (InterruptedException ex) { - Thread.currentThread().interrupt(); + return; } } events.add(ev); - for (MoveEvent action : actions) + try { - action.doAction(ev); - } + for (MoveEvent action : actions) + { + action.doAction(ev); - events.remove(ev); - moveEventWait.release(); + if (Thread.currentThread().isInterrupted()) + { + throw new InterruptedException(); + } + } + } catch (InterruptedException ex) + { + /* Swallow the interrupt because execution will drop to the finally + * and then the method will end anyway */ + } finally { + events.remove(ev); + moveEventWait.release(); + } } public static void moveAll() throws InterruptedException { - moveEventWait.acquire(100); - moveEventWait.release(100); + try + { + moveEventWait.acquire(100); + } catch (InterruptedException ex) + { + for (Future f : eventThreads) + { + f.cancel(true); + } + + throw ex; + } finally { + moveEventWait.release(100); + } } public static boolean isHeroActive() diff --git a/src/com/fourisland/fourpuzzle/window/MessageWindow.java b/src/com/fourisland/fourpuzzle/window/MessageWindow.java index 0057ca3..dab67d1 100644 --- a/src/com/fourisland/fourpuzzle/window/MessageWindow.java +++ b/src/com/fourisland/fourpuzzle/window/MessageWindow.java @@ -79,10 +79,16 @@ public class MessageWindow implements Renderable { Display.registerRenderable(mw); KeyboardInput.registerInputable(in); - cdl.await(); - - Display.unregisterRenderable(mw); - KeyboardInput.unregisterInputable(in); + try + { + cdl.await(); + } catch (InterruptedException ex) + { + throw ex; + } finally { + Display.unregisterRenderable(mw); + KeyboardInput.unregisterInputable(in); + } } public static void displayMessage(String message) throws InterruptedException -- cgit 1.4.1