Skip to content

Commit

Permalink
Introduce Kernel#callback; Mark struct members for GC
Browse files Browse the repository at this point in the history
  • Loading branch information
methodmissing committed Jul 9, 2009
1 parent 0d9759a commit 7e829d4
Show file tree
Hide file tree
Showing 3 changed files with 32 additions and 4 deletions.
2 changes: 2 additions & 0 deletions bench/raggi_bench.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ def me; @s.to_s; end
cb = Callback &ld
c2 = Callback( @s, :to_s )
rb = RubyCallback { @s.to_s }
farm = @s.callback(:to_s)

tests = 100_000
puts "# Calling"
Expand All @@ -17,4 +18,5 @@ def me; @s.to_s; end
results.report("callback:") { tests.times { cb.call } }
results.report("callbak2:") { tests.times { c2.call } }
results.report("rubyback:") { tests.times { rb.call } }
results.report("farm:") { tests.times { farm.call } }
end
22 changes: 18 additions & 4 deletions ext/callback/callback.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,20 +11,24 @@ VALUE rb_cCallback;

static ID id_call;

static void mark_callback(RCallback* cb)
{
rb_gc_mark(cb->method);
rb_gc_mark(cb->object);
}

static void free_callback(RCallback* cb)
{
xfree(cb);
}


static VALUE callback_alloc _((VALUE));
static VALUE
callback_alloc( VALUE klass )
{
VALUE cb;
RCallback* cbs;
cb = Data_Make_Struct(klass, RCallback, 0, free_callback, cbs);

cb = Data_Make_Struct(klass, RCallback, mark_callback, free_callback, cbs);
cbs->object = Qnil;
cbs->method = 0;

Expand Down Expand Up @@ -57,7 +61,7 @@ static VALUE rb_callback_initialize( int argc, VALUE *argv, VALUE cb )
return cb;
}

static VALUE rb_callback_call( VALUE cb, VALUE args )
static VALUE rb_callback_call( VALUE cb, VALUE *args )
{
RCallback* cbs = GetCallbackStruct(cb);
return rb_funcall2(cbs->object, cbs->method, -1, &args);
Expand All @@ -68,6 +72,15 @@ static VALUE rb_f_callback( int argc, VALUE *argv )
return rb_callback_initialize( argc, argv, rb_callback_new() );
}

static VALUE
rb_obj_callback( VALUE obj, VALUE mid)
{
VALUE args[2];
args[0] = obj;
args[1] = mid;
return rb_f_callback( 2, (VALUE *)args );
}

void
Init_callback()
{
Expand All @@ -80,4 +93,5 @@ Init_callback()
rb_define_method(rb_cCallback,"call", rb_callback_call, -2);

rb_define_global_function("Callback", rb_f_callback, -1);
rb_define_method(rb_mKernel, "callback", rb_obj_callback, 1);
}
12 changes: 12 additions & 0 deletions test/test_callback.rb
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,22 @@ def test_init_object_call_with_args
assert_equal 'hai', cb.call( 'b', 'h' )
end

def test_many_calls
cb = Callback { :foo }
100_000.times { cb.call }
end

def test_arguments
assert_raises ArgumentError do
Callback( 'hai' ){}
end
end

def test_farmed_from_object
cb = 'hai'.callback(:to_s)
assert_equal 'hai', cb.call
ocb = 'bai'.callback(:gsub)
assert_equal 'hai', ocb.call('b', 'h')
end

end

0 comments on commit 7e829d4

Please sign in to comment.