Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Coroutine support for Enumerator#next and #rewind. Not isolated from …

…mainline code yet.
  • Loading branch information...
commit df568534458dc9f818d49f2f09c942c0d61a3cdd 1 parent 60f553c
@headius headius authored
Showing with 62 additions and 5 deletions.
  1. +62 −5 src/org/jruby/RubyEnumerator.java
View
67 src/org/jruby/RubyEnumerator.java
@@ -30,7 +30,11 @@
import org.jruby.anno.JRubyMethod;
import org.jruby.anno.JRubyModule;
import org.jruby.javasupport.util.RuntimeHelpers;
+import org.jruby.parser.StaticScope;
+import org.jruby.runtime.Arity;
+import org.jruby.runtime.Binding;
import org.jruby.runtime.Block;
+import org.jruby.runtime.Block.Type;
import org.jruby.runtime.BlockCallback;
import org.jruby.runtime.ObjectAllocator;
import org.jruby.runtime.ThreadContext;
@@ -38,6 +42,10 @@
import org.jruby.runtime.builtin.IRubyObject;
import org.jruby.util.ByteList;
+import java.dyn.AsymCoroutine;
+import org.jruby.parser.LocalStaticScope;
+import org.jruby.runtime.BlockBody;
+
/**
* Implementation of Ruby's Enumerator module.
*/
@@ -403,14 +411,63 @@ public static IRubyObject with_index19(ThreadContext context, IRubyObject self,
}
@JRubyMethod(name = "next", frame = true)
- public static IRubyObject next(ThreadContext context, IRubyObject self) {
- context.getRuntime().getLoadService().lockAndRequire("generator_internal");
- return self.callMethod(context, "next");
+ public static IRubyObject next(final ThreadContext context, final IRubyObject self) {
+ AsymCoroutine coro = getCoro(self);
+ if (coro == null) {
+ coro = setupCoro(context, self);
+ }
+ return (IRubyObject)coro.call();
}
@JRubyMethod(name = "rewind", frame = true)
public static IRubyObject rewind(ThreadContext context, IRubyObject self) {
- context.getRuntime().getLoadService().lockAndRequire("generator_internal");
- return self.callMethod(context, "rewind");
+ setupCoro(context, self);
+ return context.getRuntime().getNil();
+ }
+
+ private static AsymCoroutine getCoro(IRubyObject self) {
+ return (AsymCoroutine)self.getInternalVariables().getInternalVariable("coro");
+ }
+
+ private static AsymCoroutine setupCoro(final ThreadContext context, final IRubyObject self) {
+ AsymCoroutine coro = new AsymCoroutine<IRubyObject, IRubyObject>() {
+ public IRubyObject run(IRubyObject value) {
+ IRubyObject result = self.callMethod(context, "each", IRubyObject.NULL_ARRAY, new Block(new BlockBody(FL_USHIFT) {
+ @Override
+ public IRubyObject yield(ThreadContext context, IRubyObject value, Binding binding, Type type) {
+ return ret(value);
+ }
+
+ @Override
+ public IRubyObject yield(ThreadContext context, IRubyObject value, IRubyObject self, RubyModule klass, boolean aValue, Binding binding, Type type) {
+ return ret(value);
+ }
+
+ StaticScope scope = new LocalStaticScope(null);
+
+ @Override
+ public StaticScope getStaticScope() {
+ return scope;
+ }
+
+ @Override
+ public void setStaticScope(StaticScope newScope) {
+ }
+
+ @Override
+ public Block cloneBlock(Binding binding) {
+ return new Block(this);
+ }
+
+ @Override
+ public Arity arity() {
+ return Arity.ONE_ARGUMENT;
+ }
+ }));
+ return result;
+ }
+ };
+ self.getInternalVariables().setInternalVariable("coro", coro);
+ return coro;
}
}
Please sign in to comment.
Something went wrong with that request. Please try again.