content: package rabbitescape.ui.android;
  
  import rabbitescape.engine.World;
  import rabbitescape.engine.textworld.TextWorldManip;
  
  /**
   * Hairy synchronization of the game loop, and the UI/system thread to
   * ensure the world saves correctly.
   *
   * Only the game loop can stop what it is doing to save the world, but
   * it is the UI/system thread that asks for the saved world.
   */
  public class WorldSaver
  {
      public static class Signal
      {
          public synchronized void listen( long wait_time )
          {
              try
              {
                  wait( wait_time );
              }
              catch ( InterruptedException e )
              {
                  // We have been notified that what we are waiting for
                  // might have arrived
              }
          }
  
          public synchronized void speak()
          {
              notify();
          }
      }
  
      private final World world;
      private final AndroidGameLaunch gameLaunch;
  
      private final Signal requestSave = new Signal();
      private final Signal saved = new Signal();
      private boolean saveWorld = false;
      public String[] savedWorld = null;
  
      public WorldSaver( World world, AndroidGameLaunch gameLaunch )
      {
          this.world = world;
          this.gameLaunch = gameLaunch;
      }
  
      /**
       * Game loop thread: checks whether we've been asked
       * to save the world, and if so, blocks here while it does it.
       */
      public void check()
      {
          if ( saveWorld )
          {
              saveWorld = false;
              savedWorld = actuallySaveWorld();
              saved.speak();
          }
      }
  
      private String[] actuallySaveWorld()
      {
          world.changes.revert();
          return TextWorldManip.renderCompleteWorld( world, true );
      }
  
      /**
       * Game loop thread: pauses the time supplied, but will
       * be interrupted if the UI/system thread wakes us up
       * by calling calls waitUntilSaved().
       */
      public void waitUnlessSaveSignal( long wait_time )
      {
          requestSave.listen( wait_time );
      }
  
      /**
       * UI/system thread: requests a world save, wakes up the
       * game loop if it is sleeping, then blocks until the game
       * loop has saved the world, which it does by calling check().
       *
       * @return the saved model
       */
      public String[] waitUntilSaved()
      {
          if ( !gameLaunch.isRunning() )
          {
              return actuallySaveWorld();
          }
  
          saveWorld = true;
          requestSave.speak();
          while ( savedWorld == null )
          {
              saved.listen( 0 );
          }
  
          String[] ret = savedWorld;
          savedWorld = null;
          return ret;
      }
  }
  