Pages

Sunday, July 27, 2008

When people fail


An alternate route must be found.

I got such a laugh out of this one.

Just make sure you read grog free and not free grog :D

Thursday, July 24, 2008

Solving the timing issue - Overkill?

So after sleeping on the problem, I came up with a solution. I need to touch the latch after the task has been done.
private Future makeMove(final Player player, final int round, final CountDownLatch latch, final ExecutorService executor)
{
  return executor.submit(new Callable()
    {
      public Choice call() throws Exception
      {
        try
        {
          Choice result = player.brain.makeMove(round);
          gameEventListener.moveMade(player, result);
          return result;
        }
        finally
        {
          executor.execute(new Runnable()
            {
              public void run()
              {
                latch.countDown();
              }
            });
        }
      }
    });
}
The trick is that I need finer control over the executer.
ExecutorService p1Executor = Executors.newFixedThreadPool(1, new DaemonThreadFactory());
ExecutorService p2Executor = Executors.newFixedThreadPool(1, new DaemonThreadFactory());
The reason I need an ExecutorService for each player is that when the first player finishes their moves, when the second player submits the “hit latch” task, it is possible that task gets executed and finished before the current task ends.

So I can finally access the get method with a 0 wait time: return future.get(0, TimeUnit.NANOSECONDS);.
I need some input though:
Is this overkill?
Is this ugly?
My first thought was that it gets the job done in very few, readable lines. So no.

Wednesday, July 23, 2008

Java Out of Order

So I've got a fairly consistant output now, and its the out of order or "optimisations" being made that I think have screwed me over.
Not really a gotcha, it's just I let him sneak up on me.
return executor.submit(new Callable()
  {
    public Choice call() throws Exception
    {
      try
      {
        Choice result = player.brain.makeMove(round);
        gameEventListener.moveMade(player, result);
        return result;
      }
      finally
      {
        latch.countDown();
      }
    }
  });
Now I don’t think there should be anyway that the latch.countDown(); could be re-ordered to come before the makeMove().
This allows me to get the result of the Futures with a very small wait: return future.get(1, TimeUnit.NANOSECONDS);.
But it still isn’t instant. My problem now being that the Future isn’t being set with the result in time. If you look at it from the other side, I’m not really hooking into the right part of the Future. I really need to trigger the countDown() after the future has been finished. The Callable interface doesn’t have any other methods I can hook into and my first search of the package leaves no leads.
At least I’m a little bit happier.

Tuesday, July 22, 2008

More Rock Paper Scissors

Long long ago, I wrote an Interface for people to write Rock Paper Scissors Bots.
We were playing around with them on one open day, I can’t believe that I didn’t blog about it.
Anyway, to distract me from my actual project, I’ve started working on it again, simplifying code and extracting out interfaces with the intention of providing more that one way to join in the tournament (which is currently only if you are specified in code).
IRC seems like a perfect alternative.
One of my first challanges was how to ask two bots for their choices, but only give a limited time before giving up. It would be cool to let humans play as well so my limit is 10 seconds at the moment. The reason I have to ask two bots at once is that I don’t want to ask bot 1, wait at most 10 seconds, then ask bot 2. Both of these can be done at once.

So, using the java.util.concurrent package, I whip up an ExecutorService. The problem with the Executors.defaultThreadFactory() is that when the program ends, those threads from the factory prevent the application from ending.
That’s easy enough to fix:
class DaemonThreadFactory implements ThreadFactory
{
  ThreadFactory impl = Executors.defaultThreadFactory();

  public Thread newThread(Runnable r)
  {
    Thread t = impl.newThread(r);
    t.setDaemon(true);
    return t;
  }
}

Now, I need to wait on two different threads, sounds like a semaphore, or a CountDownLatch in Java. I pass the latch to the Callable that will be done in the other thread.

executor.submit(new Callable()
{
  public Choice call() throws Exception
  {
    Choice result = player.brain.makeMove(round);
    latch.countDown();
    gameEventListener.moveMade(player, result);
    return result;
  }
});

Then it is just a matter of CountDownLatch.await(long timeout, TimeUnit unit)

When you submit a task to the ExecutorService, you get back a Future object which can be check if the task is done and what the result of the Callable was.

future.get(2, TimeUnit.MILLISECONDS);

And this is where the fun begins.

You’ll note that I am waiting 2 milliseconds to get the value, after waiting at most 10 seconds from the latch. I know that the methods were completed because the event “moveMade” was raised.
But sometimes, just sometimes, they get call timesout.

When I was working with Threading in Advanced .Net, I was happy debugging this sort of code because all of the utility methods were my own. I wrote them, I should know what is going on. Here I am just going off the API.

Time to “Mind Meld” with the source code of the FutureTask me thinks. It seems like there is a missing synchronized keyword somewhere but I would have thought that the FutureTask would have taken care of that for me.
I’m almost putting money on there being a “Gotchas” post being made after this one.