StandardGame Exception handling improvement

Hi,



I've updated my local copy of StandardGame to improve it's uncaught exception handling.



Basically I've created a new method that allows a UncaughtExceptionHandler to be added to the gameThread and created a new default handler.  The default handler just prints out to the logger and ends the game, which if I'm not mistaken is the same behaviour as the current try/catch block.  The obvious improvement comes if users code their own handlers which among other things could restart the game loop, open error reporting tools etc etc.



Here is a diff patch I exported using netBeans.  I'm not sure how diff patches are meant to look so if this is completely useless let me know and I'll just paste all the changed methods  :stuck_out_tongue:



# It uses platform neutral UTF-8 encoding and n newlines.
# Above lines and this line are ignored by the patching process.
Index: StandardGame.java
*** srccomjmexgameStandardGame.java Base (1.2)
--- srccomjmexgameStandardGame.java Locally Modified (Based On 1.2)
***************
*** 31,36 ****
--- 31,37 ----
   */
  package com.jmex.game;
 
+ import java.lang.Thread.UncaughtExceptionHandler;
  import java.util.concurrent.*;
  import java.util.logging.Level;
  import java.util.prefs.Preferences;
***************
*** 110,116 ****
      }
 
      public void start() {
!         gameThread = new Thread(this);
          gameThread.start();
         
          // Wait for main game loop before returning
--- 111,119 ----
      }
 
      public void start() {
!         if (gameThread == null) {
!             setUncaughtExceptionHandler(new DefaultUncaughtExceptionHandler());
!         }
          gameThread.start();
         
          // Wait for main game loop before returning
***************
*** 144,150 ****
          }
         
          // Main game loop
-         try {
              float tpf;
              started = true;
              while ((!finished) && (!display.isClosing())) {
--- 147,152 ----
***************
*** 181,190 ****
                 
                  Thread.yield();
              }
              started = false;
-         } catch(Throwable t) {
-             LoggingSystem.getLogger().log(Level.SEVERE, "Main game loop broken by uncaught exception", t);
-         }
          cleanup();
          quit();
      }
--- 183,193 ----
 
              Thread.yield();
          }
+        
          started = false;
          cleanup();
          quit();
***************
*** 431,437 ****
--- 431,468 ----
      public boolean isStarted() {
          return started;
      }
+    
+     /**
+      * Sets the uncaught exception handler on the main game thread.
+      *
+      * @param eh The uncaught exception handler.
+      */
+     public void setUncaughtExceptionHandler(UncaughtExceptionHandler eh) {
+         if (gameThread == null) {
+             gameThread = new Thread(this);
          }
+
+         gameThread.setUncaughtExceptionHandler(eh);
+     }
+    
+    
+    
+    
+    
+     private class DefaultUncaughtExceptionHandler implements UncaughtExceptionHandler {
+         public void uncaughtException(Thread t, Throwable e) {
+             if (t == gameThread) {
+                 LoggingSystem.getLogger().log(
+                         Level.SEVERE, "Main game loop broken by uncaught exception", e);
+                
+                 cleanup();
+                 quit();
+             }
+         }
+     }
+    
+ }



Anyhoo let me know what you think  :)


- Chris

I had intended adding something along these lines and I appreciate you doing the work for me. ;)  I'll try to get it added when I have a chance.  I just set up RC1 of Vista and I'm currently playing around in it and Eclipse hasn't been configured yet, so it will have to wait. :slight_smile:

Just what I was thinking! Great job.

I just saved darkfrog having to do some work?!  :?  :frowning:



Damn it!  :x




  • Chris

I added the functionality to StandardGame.  I tried applying the patch but Eclipse didn't like it so I went ahead and wrote the code the way I wanted to write it.  :stuck_out_tongue:



It's extremely similar to yours but there are also some distinctions. The functionality should be identical though.

Haha  :stuck_out_tongue:



Netbeans probably made sure Eclipse wouldn't be able to use a patch it generated on purpose!  :-o



As long as the general idea is the same then I'm happy.  I'll update tonight, thanks darkfrog  :slight_smile:




  • Chris



    ps. I didn't save you having to do work in the end! Yay!!  :D  :wink:

Incompetence can sometimes be a benefit, huh?  :stuck_out_tongue:

Quick someone get me to the Hospital; because I just got burned!  :(  :stuck_out_tongue:

Okies I've just updated and I've noticed a few things.



1)  In the default handler you just call shut down.  Doesn't that just stop the game loop running?  Which since the main game loop is already broken won't do anything except result in a 'locked' app?



2)  You don't call clean up in the default handler.



Letting clean up run seems like a good idea to me as people might need to save stuff back out when the game is ended (which could be in there GameStates clean up method).  Also I don't know if native libs (lwjgl etc) need to be cleaned up correctly?  But eitherway seems like it should be called.



3) This is potentially a major oversight on your part  :stuck_out_tongue: but you seem to have left the try/catch block in.  Which surely means there won't ever be an unhandled exception?  I'm not sure if thats how it works, but I'd assume run would have to throw an exception for it to be considered uncaught?





Feel free to sass me some more if I'm talking rubbish :stuck_out_tongue:

"Don't talk such rot!" (been playing too much Oblivion)



Yeah, you've got valid points…I was in a hurry to get this done so I could get back to working on my game. :stuck_out_tongue:



I'll try to sit down and get everything working properly.  Testing might also be necessary at some point as well…but don't press your luck. :slight_smile:

darkfrog said:

... been playing too much Oblivion ...


I don't think thats actually possible!

No mad rush here, so feel free to take your time  :)

Well, I did make the changes last night, but I believe I forgot to check it in to the repository though.  I added a couple additional features to StandardGame as well.  I'll try to remember to check in when I get home.  Too busy trying to actually write something.  I'm determined one of these days to have a full game. :o

[sorry for beeing a bit off topic]



Your Frogness!



I had a look at GameStates and StandardGames etc., and I really like the idea, however I had some difficulties when I tried to convert my SimpleGame (which was obviousely not so simple) to StandardGame. So may I humbly ask Your Frogness to complete the second Wiki tutorial (showing how to go from SimpleGame to StandardGame). I know that I request a great sacrifice from Your Frogness, especially in distracting thou from the ways of Oblivion, but doing so would increase and illuminate the glory of Your Frogness. C'mon…

hehe…well, I've actually long-since beaten Oblivion and most of my gaming has been spent trying to beat Zelda: The Twilight Princess (only a couple hours left and it should fall under my frogliness).  However, haven't had much time to do anything as I've been commuting about four hours a day to a new job.  I'm hoping to close on my new house by Friday so I'll hopefully have some free time after that.  If I do find myself without anything to do and hand cramps from Zelda though, I will try to get that wiki entry finished though.  :stuck_out_tongue: