7
\$\begingroup\$
public boolean connectedOnGameServer = false;
public final Object conGameServerMonitor = new Object();

public void connectedToGameServer() {
    synchronized (conGameServerMonitor) {
        if (connectedOnGameServer != false)
            throw new RuntimeException("Player connected twice");
        connectedOnGameServer = true;
        conGameServerMonitor.notifyAll();
    }
}

public void waitForGameServerConnection() {
    synchronized (conGameServerMonitor) {
        try {
            long startTime = System.currentTimeMillis();
            long waited = 0;
            while (!connectedOnGameServer && waited < GAMESERVER_CONNECT_TIMEOUT) {
                conGameServerMonitor.wait(GAMESERVER_CONNECT_TIMEOUT - waited);
                waited = System.currentTimeMillis() - startTime;
            }
            if (waited > GAMESERVER_CONNECT_TIMEOUT && connectedOnGameServer) {
                throw new RuntimeException("Client didn't connect to game server in time (" + GAMESERVER_CONNECT_TIMEOUT + " ms)");
            }
        } catch (InterruptedException e) {
            throw new RuntimeException("Interrupted while waiting for client to connect to game server", e);
        }
    }
}

What I need is:

  • Thread A calls waitForGameServerConnection
  • Thread B calls connectedToGameServer
  • Thread A continues
\$\endgroup\$
6
\$\begingroup\$

My code examples are excerpts. Don't copy/paste them, they are suggestions you can incorporate into your code.

if (waited > GAMESERVER_CONNECT_TIMEOUT && connectedOnGameServer)
{
   throw new RuntimeException("Client didn't connect to game server in time (" + GAMESERVER_CONNECT_TIMEOUT + " ms)");
} 

can be reduced to:

if (!connectedOnServer) {
   throw new RuntimeException("Client didn't connect to game server in time (" + GAMESERVER_CONNECT_TIMEOUT + " ms)");
}

Now, you can handle this without an exception. Connections fail quite regularly, and it's easy to handle that.

public boolean waitForConnection() {
   synchronized (conGameServerMonitor) {
      // loop, guard
      return connectedOnGameServer? true : false;
   }
}

With this you can ask the player if he wants to try again, or wait a bit and try again, etc without having to catch an exception. But what if B calls connectedToGameServer() after the wait completes?

boolean connectionInProgress;

public void connectedToGame() {
   synchronized (conGameServerMonitor) {
      if (connectionInProgress) {
         connectedOnGameServer = true;
         conGameServerMonitor.notifyAll(); 
      }
   }
}

public boolean waitForConnection() {
   synchronized (conGameServerMonitor) {
      connectionInProgress = true;
      // wait
      connectionInProgress = false;
      return connectedOnGameServer? true : false;
   }
}

You handle the wakeups and interuptions correctly. Kudos for the waited part - I thought "Useless!" for a second, but I forgot that a thread could wake anytime, and it's the thread's responsibility to be sure that it's conditions are fulfilled.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.