Question

I have a bunch of procedures that need to be executed successively until either they are all executed, or a certain condition is met. Here's the basic code that needs to be executed until a condition is met:

public boolean search()
{
    robot.go();

    robot.spin();

    //etc - around 8 more similar commands (each takes around 2 seconds)
    return false; //didn't find what it was looking for
}

So far, the only way that I've thought of doing what I wanted is this:

public boolean search()
{
    robot.go(false);
    while(robot.isMoving())
    {
        if(thingFound())
        {
            robot.stop()
            return true;
        }
        Thread.yield();
    }

    robot.spin(false);
    while(robot.isMoving())
    {
        if(thingFound())
        {
            robot.stop()
            return true;
        }
        Thread.yield();
    }


    //etc - around 8 more similar commands
    return false; //didn't find what it was looking for
}

The false parameter to go() and spin() indicates that they should return immediately, allowing the condition to be checked. However, this approach strikes me as rather inefficient, as the same block of code must be repeated 10 times. Could this be achieved more efficiently with exceptions or concurrent Threads?

Was it helpful?

Solution

based on Jonathan Leffler's answer:
you can use a Runnable as pointer to the commands

private final Runnable going = new Runnable() {
    @Override
    public void run() {
        robot.go(false);
    }
});

private final Runnable spinning = new Runnable {
    @Override
    public void run() {
        robot.spin(false);
    }
});

// other commands 


private boolean isFoundAfter(Runnable command)
{
    command.run();
    while (robot.isMoving())
    {
        if (thingFound())
        {
            robot.stop()
            return true;
        }
        Thread.yield();
    }
    return false;
}

public boolean search()
{
    if (isFoundAfter(going)) return true;

    if (isFoundAfter(spinning)) return true;   

    //etc - around 8 more similar commands
    return false; //didn't find what it was looking for
}


one further step, if appropriate, put the commands in an array or a List and execute it as a script

...

private boolean executeSearch(Runnable... commands)
{
    for (Runnable cmd : commands) {
        if (isFoundAfter(cmd)) return true;
    }
    return false; //didn't find what it was looking for
}

public boolean search() {
    return executeSearch(going, spinning /* around 8 more similar commands */);
}

OTHER TIPS

Not sure why you are using Thread.yield() - are there other threads executing that you didn't mention? Or maybe I misread the problem.

I think maybe the Command pattern could work here. You would have a RobotCommand interface with an execute method, and an implementation of RobotCommand per command type (go, spin, etc). Then you could construct a RobotAlgorithm as a List of RobotCommand, and have a method executeRobotAlgorithm that iterated over the list, calling execute on each RobotCommand and checking the result of thingFound() after each one.

Edit - oh, I think I get it. Do go and spin kick off threads that change the state of the robot, or something like that?

Edit 2 - in response to your comment, it sounds like the problem here is that you need to be able to return immediately if the robot finds what it's looking for, but the go, spin, etc commands won't do this right now, and you need the ability to keep executing new commands in the meantime. So what I might do here is have two threads - one would be an "executor" thread that would execute your List of RobotCommands one by one, and a "watcher" thread that will repeatedly sleep and poll (check thingFound()). If thingFound() is ever true then you can stop your robot as well as the executor thread, or if the executor gets to the end before thingFound() is true then it can signal as such (if necessary).

Clearly, the while loop can be packaged into its own function:

private boolean isFound()
{
    while (robot.isMoving())
    {
        if (thingFound())
        {
            robot.stop()
            return true;
        }
        Thread.yield();
    }
    return false;
}

public boolean search()
{
    robot.go(false);
    if (isFound()) return true;

    robot.spin(false);
    if (isFound()) return true;   

    //etc - around 8 more similar commands
    return false; //didn't find what it was looking for
}

(I don't mind if the conditional is split over two lines; I'd probably do that in production code.)

A better Java programmer than I can tell you whether you can pass 'procedures' around (pointers to functions, in terms of C programming). I suspect you can, but I don't know the syntax and rules. The evidence seems to be that you can't (circa 2004, anyway).

robot can use a Condition object to signal to the controller that it's completed some sub-task or entered a new state:

http://java.sun.com/j2se/1.5.0/docs/api/java/util/concurrent/locks/Condition.html

interesting, for the environment that's in you could probably use and notify() and wait() instead of the more flexible Condition. controller could wait() until the robot decides to release him with notify().

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top