Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions deps/mruby-class-new-fiber-safe/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
*.swp
*.old
*/*.dSYM/
.DS_Store
mruby/
tmp/
6 changes: 6 additions & 0 deletions deps/mruby-class-new-fiber-safe/.travis.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
sudo: false
script:
- export MRUBY_CONFIG="$TRAVIS_BUILD_DIR/.travis_config.rb"
- git clone --depth 1 "https://github.com/mruby/mruby.git"
- cd mruby
- ./minirake test
8 changes: 8 additions & 0 deletions deps/mruby-class-new-fiber-safe/.travis_config.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
MRuby::Build.new do |conf|
toolchain :gcc
enable_debug
conf.enable_bintest
conf.enable_test
conf.gembox 'default'
conf.gem '../mruby-class-new-fiber-safe'
end
13 changes: 13 additions & 0 deletions deps/mruby-class-new-fiber-safe/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
mruby-class-new-fiber-safe
====

[![Build Status](https://travis-ci.org/kazuho/mruby-class-new-fiber-safe.svg?branch=master)](https://travis-ci.org/kazuho/mruby-class-new-fiber-safe)

Class#new that allows the use of fiber in constructor.

See also: https://github.com/mruby/mruby/issues/3879

Acknowledgements
----

Advices from [@miura1729](https://github.com/miura1729) and [@take-cheeze](https://github.com/take-cheeze) helped a lot in writing this mrbgem.
7 changes: 7 additions & 0 deletions deps/mruby-class-new-fiber-safe/mrbgem.rake
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
MRuby::Gem::Specification.new('mruby-class-new-fiber-safe') do |spec|
spec.license = 'MIT'
spec.author = 'mruby developers, Kazuho Oku'
spec.version = '0.0.1'
spec.add_dependency('mruby-fiber', :core => 'mruby-fiber')
spec.summary = 'Class#new that allows use of fiber in constructor'
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
class Class
def new(*args, &block)
obj = self.allocate
obj.initialize(*args, &block)
obj
end
end
31 changes: 31 additions & 0 deletions deps/mruby-class-new-fiber-safe/src/class-new-fiber-safe.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
#include <stdlib.h>
#include <mruby.h>
#include <mruby/class.h>

/* copy of mrb_instance_alloc (see include/mruby.h for copyright) */
static mrb_value class_allocate(mrb_state *mrb, mrb_value cv)
{
struct RClass *c = mrb_class_ptr(cv);
struct RObject *o;
enum mrb_vtype ttype = MRB_INSTANCE_TT(c);

if (c->tt == MRB_TT_SCLASS)
mrb_raise(mrb, E_TYPE_ERROR, "can't create instance of singleton class");

if (ttype == 0) ttype = MRB_TT_OBJECT;
if (ttype <= MRB_TT_CPTR) {
mrb_raisef(mrb, E_TYPE_ERROR, "can't create instance of %S", cv);
}
o = (struct RObject*)mrb_obj_alloc(mrb, ttype, c);
return mrb_obj_value(o);
}

void mrb_mruby_class_new_fiber_safe_gem_init(mrb_state* mrb)
{
struct RClass *cls = mrb->class_class;
mrb_define_method(mrb, cls, "allocate", class_allocate, MRB_ARGS_NONE());
}

void mrb_mruby_class_new_fiber_safe_gem_final(mrb_state* mrb)
{
}
14 changes: 14 additions & 0 deletions deps/mruby-class-new-fiber-safe/test/class-new-fiber-safe.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
class C
def initialize(v)
Fiber.yield(v)
end
end

assert("Class#new") do
f = Fiber.new do
C.new(123)
end
assert_equal f.resume, 123
assert_false Module.method_defined? :allocate
assert_true Class.method_defined? :allocate
end
24 changes: 24 additions & 0 deletions t/50mruby-channel.t
Original file line number Diff line number Diff line change
Expand Up @@ -116,4 +116,28 @@ EOT

};

subtest "fiber-switch in constructor" => sub {
my $server = spawn_h2o(<< 'EOT');
hosts:
default:
paths:
/:
mruby.handler: |
class Klass
def initialize(ch)
task do
ch.push [200, {}, ["hello world"]]
end
end
end
Proc.new do |env|
ch = H2O::Channel.new
Klass.new(ch)
ch.shift
end
EOT
my ($stderr, $stdout) = run_prog("curl --silent --dump-header /dev/stderr http://127.0.0.1:$server->{port}/");
is $stdout, "hello world";
};

done_testing();