summaryrefslogtreecommitdiffhomepage
path: root/mrbgems/mruby-fiber
diff options
context:
space:
mode:
authortake_cheeze <[email protected]>2014-03-21 06:16:40 +0900
committertake_cheeze <[email protected]>2014-03-21 22:10:47 +0900
commitd4d4f1b0d57bed96bb3341c2304e39afefa352c5 (patch)
tree7b5b2abe9d0c4a2054793b50c06b59f09441efb7 /mrbgems/mruby-fiber
parent07bd65ae65ba1092191f5a702ce3c15aaca2ab5f (diff)
downloadmruby-d4d4f1b0d57bed96bb3341c2304e39afefa352c5.tar.gz
mruby-d4d4f1b0d57bed96bb3341c2304e39afefa352c5.zip
implement Fiber#transfer
Diffstat (limited to 'mrbgems/mruby-fiber')
-rw-r--r--mrbgems/mruby-fiber/src/fiber.c13
-rw-r--r--mrbgems/mruby-fiber/test/fiber.rb19
2 files changed, 32 insertions, 0 deletions
diff --git a/mrbgems/mruby-fiber/src/fiber.c b/mrbgems/mruby-fiber/src/fiber.c
index 433b11693..b5f9b69dc 100644
--- a/mrbgems/mruby-fiber/src/fiber.c
+++ b/mrbgems/mruby-fiber/src/fiber.c
@@ -226,6 +226,18 @@ fiber_eq(mrb_state *mrb, mrb_value self)
return mrb_bool_value(fiber_ptr(self) == fiber_ptr(other));
}
+static mrb_value
+fiber_transfer(mrb_state *mrb, mrb_value self)
+{
+ mrb_value result = fiber_resume(mrb, self);
+
+ mrb_assert(mrb->c->prev);
+ mrb_assert(mrb->c->prev->prev);
+ mrb->c->prev->status = MRB_FIBER_SUSPENDED;
+ mrb->c->prev = mrb->c->prev->prev;
+
+ return result;
+}
mrb_value
mrb_fiber_yield(mrb_state *mrb, int len, mrb_value *a)
@@ -300,6 +312,7 @@ mrb_mruby_fiber_gem_init(mrb_state* mrb)
mrb_define_method(mrb, c, "initialize", fiber_init, MRB_ARGS_NONE());
mrb_define_method(mrb, c, "resume", fiber_resume, MRB_ARGS_ANY());
+ mrb_define_method(mrb, c, "transfer", fiber_transfer, MRB_ARGS_ANY());
mrb_define_method(mrb, c, "alive?", fiber_alive_p, MRB_ARGS_NONE());
mrb_define_method(mrb, c, "==", fiber_eq, MRB_ARGS_REQ(1));
diff --git a/mrbgems/mruby-fiber/test/fiber.rb b/mrbgems/mruby-fiber/test/fiber.rb
index e10878bf4..c6f9d821f 100644
--- a/mrbgems/mruby-fiber/test/fiber.rb
+++ b/mrbgems/mruby-fiber/test/fiber.rb
@@ -8,6 +8,25 @@ assert('Fiber#resume') {
f.resume(2)
}
+assert('Fiber#transfer') do
+ f1 = Fiber.new do |v|
+ assert_raise(FiberError) { Fiber.current.transfer }
+ Fiber.yield v
+ end
+ f2 = Fiber.new do
+ f1.transfer(1)
+ Fiber.yield 2
+ end
+ assert_equal 1, f2.resume
+ assert_equal 2, f2.resume
+ f1.resume
+ f2.resume
+ assert_false f1.alive?
+ assert_false f2.alive?
+
+ assert_raise(FiberError) { Fiber.current.transfer }
+end
+
assert('Fiber#alive?') {
f = Fiber.new{ Fiber.yield }
f.resume