Closed claytonlemons closed 9 years ago
Hey,
The problem you're having is that your echo method isn't being instrumented. The reason for this is that the instrumenter (called from the maven plugin) will only instrument methods that take in a Continuation as a parameter. Trying to grab a Continuation object out of a field and calling suspend() on it won't work.
This is noted in the Explanation section of the README (just above the FAQ section). Important portion is as follows...
Any method that takes in a Continuation type as a parameter will be instrumented by the plugin to work as part of a coroutine.
If you update your code to the following, I bet it'll work.
public void run(Continuation c) {
System.out.println("started!");
for (int i = 0; i < 10; i++)
{
echo(c, i);
}
}
private void echo(Continuation c, int x) {
System.out.println("in echo!");
System.out.println(x);
c.suspend();
}
I'll keep this ticket open for a few days in case your problem isn't solved by this change.
Possible action item:
Explicitly and overtly state the parameter requirement in the example section of the README.
Possible action item:
Wording in explanation section may be too ambiguous.
Thanks Kasra!
That was the issue all along. My program is working correctly now for the most part. There is another exception I came across that I'll post as a separate issue.
The reason I chose to make the Continuation object a class member is because my use case involves exposing a thread class (LockeThread) as part of a recursive thread pool library. LockeThread has the following methods: run(), fork() and join(). Clients override run() and call fork()/join() to implement recursive tasks. I wanted to hide the Continuation parameter so that clients would not need to worry about passing it around.
Out of curiosity, would it not be possible to annotate stack-saveable methods using something like @Continuable?
Hey,
I think there are a couple of problems with this approach.
First is that versions of Java that don't support annotations won't work anymore. I think this includes anything below 1.5.
Second (most important) is that you introduce ambiguity by not passing in the Continuation object as a parameter. Passing in the Continuation object as a parameter acts as both a marker (equivalent to an annotation) and a guarantee that the Continuation object you're using is the one you want (it gets passed down the stack with the invocation chain). If you have the ability to grab a Continuation object from anywhere and call suspend on it, there's nothing stopping you from calling suspend on the wrong Continuation object / calling suspend on the correct Continuation object but at the wrong time or in the wrong state.
I understand that the design choices I made may not mesh well with your project's API. It's a little more rigid that Javaflow, but that rigidity also increases performance and is intended to make things less ambiguous. If you can't make it work, I would encourage you to take a look at the code and potentially create a fork to better fit your usecase.
Just a heads up: There's an instrumentation bug in 1.1.0 where the Maven plugin crashes if it encounters arrays in certain rare cases. It's been fixed in 1.1.1, but hasn't been released yet.
The README has been updated. The following was added
// IMPORTANT: Methods that are intended to be run as part of a coroutine // must take in a Continuation type as a parameter. Otherwise, they // won't be marked for instrumentation.
- Question and answer about annotation moved to FAQ (with some tweaks)
Why not use annotations?
I wanted to hide the Continuation parameter so that clients would not need to worry about passing it around.
... snip ...
Out of curiosity, would it not be possible to annotate stack-saveable methods using something like @Continuable?
There are a couple of issues with using annotations ...
- First is that versions of Java that don't support annotations won't work anymore. This includes anything below 1.5.
- Second (most important) is that you introduce ambiguity by not passing in the Continuation object as a parameter. Passing in the Continuation object as a parameter acts as both a marker (equivalent to an annotation) and a guarantee that the Continuation object you're using is the one you want (it gets passed down the stack with the invocation chain). If instead of passing as a parameter, you were to use a Continuation object taken from some external source (e.g. a field or the return value of a method), there's more of a chance that you'll end up calling suspend on the wrong Continuation object / calling suspend on the correct Continuation object but at the wrong time or in the wrong state.
Closing this ticket EOD today.
Hi Kasra,
I'm very interested in using coroutines for my project, but I've run into a snag with getting a simple test to run. The exception I get tells me that I haven't instrumented my code, but I'm certain I have. Am I missing something obvious?
I've included my test code, the execution command, the exception, a log of running maven on my project, and my pom.xml. Please let me know if there is any other information that would help.
Here is my test.
Here is the command that eclipse is executing:
Here is the exception that I get when I try to run my test. I understand what the exception is, but I'm confused because I'm positive that my code has been instrumented. The log file seems to verify that.
Here is the log file from running
mvn -X compile test-compile
I can see that the instrumenter gets created and executed on each class file, including CoroutineTest$MyCoroutine, and the size of CoroutineTest$MyCoroutine changes from 1342 to 1437, indicating that something was changed.Finally, here is my pom.xml file. I'm pretty sure it is configured correctly because user-1.1.0.jar shows up as a dependency in my project, and I can run the instrument and test-instrument goals
Other things I have tried: I have verified that the file that was instrumented is indeed the file I'm trying to execute. I also tried downgrading to 1.0.4, but that didn't help.
Any ideas?
Thanks!