0

Is it possible to create a method that can temporarily pause itself by "returning" and then resuming when it is called again? It should act as if it never returned (i.e. retain all its variables, continue executing the next line, etc.).

public static void main(String args) {
   method(); //should start method
   //do stuff ONLY AFTER method() RETURNS
   method(); //should continue method at same place as it ended
   //do more stuff ONLY AFTER method() RETURNS
}

private static void method() {
   while(true) {
        //do stuff
        return;

        //do different stuff
        return;

        //do a third thing
        return;

        //then start all over
    }
}

I saw a few questions on StackOverflow that are similar, but none of the answers seemed sufficient or explanatory.

golddove
  • 1,165
  • 2
  • 14
  • 32
  • May I ask what you need this for? – Keppil Jan 31 '14 at 06:02
  • What are you really trying to do? – selbie Jan 31 '14 at 06:03
  • It already is pausing? It executes the code in a sequential order. What exactly is the problem? Or perhaps I don't understand the question. – Josh M Jan 31 '14 at 06:08
  • @JoshM Note that I said it should retain all its variable and continue executing at the same line that it returned. That example is extremely simplified from my program. – golddove Jan 31 '14 at 06:09
  • 2
    Make all the variables non-local, declare them outside the method in class. – Keerthivasan Jan 31 '14 at 06:10
  • @Keppil I essentially have a loop in the main method that does some things. However, at the beginning of each iteration of the loop, I want to do something else. This is second thing is in a separate method. The problem with simply adding a method call at the beginning of the loop is that I need some persistent variables (I cannot have the method restart). Now, of course, I can do this by simply adding the code at the beginning of the loop and having variables declared outside of the loop, but I need to do this in several places, so I want to seperate it out into a method. – golddove Jan 31 '14 at 06:12
  • @Octopus It is not just variables, I also want it to continue execution at that point. For example, it might be: while(true) { //do stuff return; //do different stuff return; //do a third thing return; //then start all over } – golddove Jan 31 '14 at 06:14
  • That code may look bad in a comment. I have updated my question with the same code. – golddove Jan 31 '14 at 06:17
  • 1
    @golddove - What you are asking for hasn't been invented yet.If you don't want to store "state" in a class instance variable, then you might be able to fake it with some sort of closure/lambda thing, but it won't be pretty. – selbie Jan 31 '14 at 06:18
  • @selbie I just found an answer to a similar question on StackOverflow. I am not really sure what syncronized() is, but it seems like you understand my question. Does this answer apply to me? http://stackoverflow.com/questions/10565172/pause-a-method-until-it-gets-called-again – golddove Jan 31 '14 at 06:22
  • @golddove - that question and answer is all about pausing a thread. Trying to adapt this solution to your single threaded problem would be complete overkill. Octopus has given you a reasonable pattern to apply. – selbie Jan 31 '14 at 06:30
  • @selbie Oh ok, I did not realized that it was threaded! Unfortunately, Octopus' answer dodges my question – golddove Jan 31 '14 at 06:34
  • 1
    @selbie C# has a couple of features that are very similar to this (yield return and await), so it certainly has been invented. It's just that Java doesn't support anything like this. – svick Jan 31 '14 at 14:19

5 Answers5

1

I think you're approaching the problem the wrong way, but if you insist, you could pass the state as parameters to the method or put the method in a different class and keep the state as instance variables

Camilo
  • 1,889
  • 2
  • 17
  • 16
1

What you are looking for is similar to the yield return statement of C#: http://msdn.microsoft.com/en-us/library/9k7k7cf0.aspx

As far as I know, there is no similar construct for Java. If you are really desperate and not shy of heavy bytecode manipulation, you could get something rolling on you own:

First create a class with a static method named yieldReturn(). Then you could search all your classes for calls to that method and perform a modification along the lines of http://csharpindepth.com/articles/chapter6/iteratorblockimplementation.aspx

ruediste
  • 2,434
  • 1
  • 21
  • 30
  • I suspected that. It seems like your answer will work, but I am not nearly as experienced to mess with bytecode :) – golddove Jan 31 '14 at 06:30
  • 1
    Check this out: http://stackoverflow.com/questions/2352399/yield-return-in-java There is a link to an existing implementation: http://chaoticjava.com/yielder/api/ – ruediste Jan 31 '14 at 06:31
  • Thanks! I had seen that question earlier, but neglected it after I saw the first answer. I will look into that implementation. – golddove Jan 31 '14 at 20:33
0

I have not seen any effective continuation implementation in java, but there is another approach that might help you.

Actors (for instance Akka) can be used to implement finite state machines, especially since they 'switch context' and 'become' another state.

Effectively each method would manipulate the state, and before ending, the actor would switch to this enhanced state.

I find the approach easy enough compared to continuations, which can be somewhat enigmatic.

Niels Bech Nielsen
  • 4,777
  • 1
  • 21
  • 44
0

Since it's tagged 'miltithreading', I guess the 'classic' way would be to thread off 'method()', make it an infinite loop and, instead of call/return, use wait/notify, or condvars, or a binary semaphore to exchange a flow 'token'.

Martin James
  • 24,453
  • 3
  • 36
  • 60
0

You can emulate a corutine like this:

class Coruntine extends Thread {
    Semaphore in = new Semaphore(0);
    Semaphore out = new Semaphore(0);
    boolean started=false;

    public Coruntine() {
        super.setDaemon(true);
    }

    public void method() {
        if (started) {
           in.release();
        } else {
            started=true;
            start();
        }
        try {
            out.acquire();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public void _return() {
        out.release();
        try {
            in.acquire();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public void run() {
        while (true) {
            System.out.println("do stuff 1");
            _return(); // like return

            System.out.println("do stuff 2");
            _return();

            System.out.println("do stuff 3");
            _return();

            // then start all over
        }
    }
}

public static void main(String[] args) {
    Coruntine c = new Coruntine();
    c.method(); // should start method
    System.out.println("do stuff AFTER method() RETURNS 1");
    c.method(); // should continue method at same place as it ended
    System.out.println("do stuff AFTER method() RETURNS 2");
    c.method(); // should continue method at same place as it ended
    System.out.println("do stuff AFTER method() RETURNS 3");
    c.method(); // should continue method at same place as it ended
    System.out.println("do stuff AFTER method() RETURNS 4");
}

if method() should return value and/or accept parameters, use blocking queues instead of semaphore(s).

Alexei Kaigorodov
  • 13,189
  • 1
  • 21
  • 38