offbynull / coroutines

Java toolkit that allows you to write coroutines.
GNU Lesser General Public License v3.0
346 stars 53 forks source link

How to get current Coroutine and suspend it #81

Closed yanxinyuan closed 6 years ago

yanxinyuan commented 6 years ago

Actually i don't know if this is a requirement or an issue. Recently i was working on introducing coroutines to our application to solve multiple thread performance issue. I do some performance testing, and indeed it does better than our original thread model. So thank you for your great effort here.

When we migrate from thread model to Coroutine, we encountered some difficulties, here is the scenario. Basically the biggest problem is how to get the current Coroutine and suspend it without passing the Continuation parameter.

class CoroutineTask implements  Coroutine {
    public void run(Continuation c) {  
                Class clazz = Class.forName("xxx");
        Object instance = clazz.newInstance();
        Method method = clazz.getMethod("yyy");
        method.invoke(instance);
       } 
}

class xxx{
    public void yyy() {
        // do something

             -> // get current Coroutine and suspend it, how to do here ?

               // continue do something
    }
}

It's more like i require a function similar as "Thread.currentThread()" in JDK, so i can get the current Coroutine and suspend it.

yanxinyuan commented 6 years ago

Because of Coroutines is implemented by bytecode manipulation. So i know it's hard to judge which method to instrument. If there is any tricksy solution?

offbynull commented 6 years ago

What your asking for isn't directly possible. The Continuation parameter is required for multiple reasons...

  1. it identifies which methods need to be instrumented
  2. it's the fastest way for your coroutine to access its internal data structures
  3. it prevents you from having broken coroutine call chains

For the type of stuff you're trying to do, you can get similar behaviour by launching a new coroutine within your existing coroutine. If you need to retain state between the outer and inner coroutine, you can pass data using the following methods...

yanxinyuan commented 6 years ago

thanks @offbynull , do you mean something like the code as this?

class OuterTask implements Coroutine {  

    public void run(Continuation c) {  
        CoroutineRunner trunner = new CoroutineRunner(new InnerTask());
        trunner.setContext(input);
        boolean notFinish = trunner.execute();
        while (notFinish) {
            c.suspend();
            notFinish = trunner.execute();
        }
        Object output = trunner.getContext();
        // handle output
    } 

} 

class InnerTask implements Coroutine {

    public void run(Continuation c) throws Exception {
        Object input = c.getContext();
        Object output = method(c, input);
        c.setContext(output);
    }

    public Object method(Continuation c, Object input) {
        // do something
        c.suspend();
        // continue do something and return
    }
}

Passing context to control the state of each Coroutine. Through this I can solve some part of my issue.

offbynull commented 6 years ago

Yes.

yanxinyuan commented 6 years ago

ok, thanks @offbynull and close the issue.