The Artima Developer Community
Sponsored Link

Make Room for JavaSpaces, Part III
Coordinate your Jini Apps with JavaSpaces
by Susan Hupfer
First Published in JavaWorld, March 2000

<<  Page 7 of 10  >>

Advertisement

The Game Service Proxy

The game service interface (defined in GameServiceInterface.java) looks like this:



public interface GameServiceInterface {

    public void setSpace(JavaSpace space);
    public Game joinGame(String name);
    public void leaveGame();
}

The GameServiceProxy class (defined in GameService.java) provides an implementation of this interface as shown here:



class GameServiceProxy implements Serializable, GameServiceInterface {
    private JavaSpace space;
    private String name;
    private Game game;

    public GameServiceProxy() {
    }
    
    public void setSpace(JavaSpace space) {
        this.space = space;
    }
    
    // To join the game, obtain a ticket to the game from the space
    public Game joinGame(String name) {
        this.name = name;
        System.out.println("Trying to get ticket to " + name);
        
        Ticket ticketTemplate = new Ticket(name);
        Ticket ticket;
        try {
            ticket = (Ticket)space.take(ticketTemplate, null, Long.MAX_VALUE);
            this.game = ticket.game;
            System.out.println("Got a ticket to " + name);  
        } catch (Exception e) {
            e.printStackTrace();
        }        
        return game;      
    }
    
    // When leaving the game, write a ticket to the game back to the space
    public void leaveGame() {
        if (game == null) {
            System.out.println("Not participating in a game!");
        } else {
            Ticket ticketEntry = new Ticket(name, game);
            try {        
                space.write(ticketEntry, null, Lease.FOREVER);
            } catch (Exception e) {
                e.printStackTrace();
            }
            System.out.println("Left the game " + name);
            name = null;
            game = null;
        }
    }
}

Earlier you saw how the game service instantiates a game service proxy and then calls its setSpace method to stash a remote reference to the JavaSpace in which the game service stores tickets. You've also seen how players -- once they've used Jini lookup to find the game service proxy -- enter a loop in which they repeatedly join the game, play for a while, and leave the game.

It's time I show you how joining and leaving are implemented. The joinGame method takes the name of the game the player wishes to join as an argument, and stashes the name in the member variable name for future reference. Then it creates an entry template from Ticket that contains the name of this particular game. With a template in hand, you call take on the space to retrieve a ticket entry. This is where the built-in synchronization of space operations comes into play: if the game is already full to capacity, then there are currently no tickets for this game in the space and take waits as long as necessary for a ticket to arrive. There could be many players waiting in joinGame's take method. Once you've retrieved a ticket to the game, you pick up the reference to the remote game that the game service stashed in the ticket and you assign it to the member variable game. The reference is also returned by the joinGame method.

At this point, the pool of tickets available in the space has been reduced by one, and the player who called joinGame holds a ticket and is free to play the game. In fact, you'll recall that the player calls play on the game object returned by joinGame. When finished playing, the player calls leaveGame. Let's take a look at what this method does. Note that you don't need to pass a game name to leaveGame, since the proxy has already stored the name in its variable name.

First, the method checks the variable game to make sure that the player is already in a game (you can't leave a game if you're not playing one!). If that test is passed, you create a new Ticket entry, filling in its fields with the name and remote reference for the game currently being played (in other words, the one the player holds a ticket for). Then you write that ticket entry into the space and reset the game and name member variables to null to reflect that you've left the game.

Let's consider what happens when the player writes a Ticket to the game back into the space. Figure 2 may help you visualize what's happening. If no other players are waiting to play the game, the ticket just remains in the space. If on the other hand, many players are waiting (in other words, many players are blocked on joinGame's take method), then one will be lucky enough to snatch up the replaced ticket, complete its call to joinGame, and proceed to play. In this example, you have no control over who will get the ticket, but you could certainly devise a more sophisticated first-come, first-served scheme that requires players to queue up when they want tickets.

There you have it: with just a few JavaSpaces operations, you've managed to coordinate any number of players that want access to your game.


Figure 2. Players coordinating their access to the game through a JavaSpace

<<  Page 7 of 10  >>


Sponsored Links



Google
  Web Artima.com   
Copyright © 1996-2017 Artima, Inc. All Rights Reserved. - Privacy Policy - Terms of Use - Advertise with Us