methodmissing-callback 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/README ADDED
@@ -0,0 +1,42 @@
1
+ Simple native Callback object for Ruby MRI
2
+ (c) 2009 Lourens Naudé (methodmissing), James Tucker (raggi) and coderrr
3
+
4
+ http://github.com/methodmissing/callback
5
+
6
+ This library works with Ruby 1.8 and 1.9 and is a more efficient
7
+ implementation of the following Ruby code :
8
+
9
+ class RubyCallback
10
+ def initialize(object = nil, method = :call, &b)
11
+ @object, @method = object, method
12
+ @object ||= b
13
+ end
14
+
15
+ def call(*args)
16
+ @object.__send__(@method, *args)
17
+ end
18
+ end
19
+
20
+ module Kernel
21
+ private
22
+ def RubyCallback(object = nil, method = :call, &b)
23
+ RubyCallback.new(object, method, &b)
24
+ end
25
+ end
26
+
27
+ Concept, ideas and API design James's - any pointers for better GC integration much appreciated.
28
+
29
+ Examples :
30
+
31
+ 'hai'.callback(:gsub).call('h', 'b') #=> 'bai'
32
+ Callback( 'bai', :to_s ).call #=> 'hai'
33
+ Callback{ 'hai' }.call #=> 'hai'
34
+ Callback( 'bai', :gsub ).call( 'b', 'h' ) #=> 'hai'
35
+
36
+ To run the test suite:
37
+
38
+ rake
39
+
40
+ To run the benchmarks:
41
+
42
+ rake bench
data/Rakefile ADDED
@@ -0,0 +1,69 @@
1
+ require 'rake'
2
+ require 'rake/testtask'
3
+ require 'rake/clean'
4
+
5
+ CB_ROOT = 'ext/callback'
6
+
7
+ desc 'Default: test'
8
+ task :default => :test
9
+
10
+ desc 'Run callback tests.'
11
+ Rake::TestTask.new(:test) do |t|
12
+ t.libs = [CB_ROOT]
13
+ t.pattern = 'test/test_*.rb'
14
+ t.verbose = true
15
+ end
16
+ task :test => :build
17
+
18
+ namespace :build do
19
+ file "#{CB_ROOT}/callback.c"
20
+ file "#{CB_ROOT}/extconf.rb"
21
+ file "#{CB_ROOT}/Makefile" => %W(#{CB_ROOT}/callback.c #{CB_ROOT}/extconf.rb) do
22
+ Dir.chdir(CB_ROOT) do
23
+ ruby 'extconf.rb'
24
+ end
25
+ end
26
+
27
+ desc "generate makefile"
28
+ task :makefile => %W(#{CB_ROOT}/Makefile #{CB_ROOT}/callback.c)
29
+
30
+ dlext = Config::CONFIG['DLEXT']
31
+ file "#{CB_ROOT}/callback.#{dlext}" => %W(#{CB_ROOT}/Makefile #{CB_ROOT}/callback.c) do
32
+ Dir.chdir(CB_ROOT) do
33
+ sh 'make' # TODO - is there a config for which make somewhere?
34
+ end
35
+ end
36
+
37
+ desc "compile callback extension"
38
+ task :compile => "#{CB_ROOT}/callback.#{dlext}"
39
+
40
+ task :clean do
41
+ Dir.chdir(CB_ROOT) do
42
+ sh 'make clean'
43
+ end if File.exists?("#{CB_ROOT}/Makefile")
44
+ end
45
+
46
+ CLEAN.include("#{CB_ROOT}/Makefile")
47
+ CLEAN.include("#{CB_ROOT}/callback.#{dlext}")
48
+ end
49
+
50
+ task :clean => %w(build:clean)
51
+
52
+ desc "compile"
53
+ task :build => %w(build:compile)
54
+
55
+ task :install do |t|
56
+ Dir.chdir(CB_ROOT) do
57
+ sh 'sudo make install'
58
+ end
59
+ end
60
+
61
+ desc "clean build install"
62
+ task :setup => %w(clean build install)
63
+
64
+ desc "run benchmarks"
65
+ task :bench do |t|
66
+ ruby "bench/bench.rb"
67
+ ruby "bench/raggi_bench.rb"
68
+ end
69
+ task :bench => :build
data/bench/bench.rb ADDED
@@ -0,0 +1,14 @@
1
+ require "benchmark"
2
+ $:.unshift "."
3
+ require File.dirname(__FILE__) + "/../ext/callback/callback"
4
+ require File.dirname(__FILE__) + "/pure_ruby_cb"
5
+
6
+ TESTS = 10_000
7
+ Benchmark.bmbm do |results|
8
+ results.report("Callback{ 'hai' }.call") { TESTS.times { Callback{ 'hai' }.call } }
9
+ results.report("RubyCallback{ 'hai' }.call") { TESTS.times { RubyCallback{ 'hai' }.call } }
10
+ results.report("Callback( 'bai', :to_s ).call") { TESTS.times { Callback( 'bai', :to_s ).call } }
11
+ results.report("RubyCallback( 'bai', :to_s ).call") { TESTS.times { RubyCallback( 'bai', :to_s ).call } }
12
+ results.report("Callback( 'bai', :gsub ).call( 'b', 'h' )") { TESTS.times { Callback( 'bai', :gsub ).call( 'b', 'h' ) } }
13
+ results.report("RubyCallback( 'bai', :gsub ).call( 'b', 'h' )") { TESTS.times { RubyCallback( 'bai', :gsub).call( 'b', 'h' ) } }
14
+ end
@@ -0,0 +1,17 @@
1
+ class RubyCallback
2
+ def initialize(object = nil, method = :call, &b)
3
+ @object, @method = object, method
4
+ @object ||= b
5
+ end
6
+
7
+ def call(*args)
8
+ @object.__send__(@method, *args)
9
+ end
10
+ end
11
+
12
+ module Kernel
13
+ private
14
+ def RubyCallback(object = nil, method = :call, &b)
15
+ RubyCallback.new(object, method, &b)
16
+ end
17
+ end
@@ -0,0 +1,23 @@
1
+ require "benchmark"
2
+ $:.unshift "."
3
+ require File.dirname(__FILE__) + "/../ext/callback/callback"
4
+ require File.dirname(__FILE__) + "/pure_ruby_cb"
5
+
6
+ @s = 'foo'
7
+ def me; @s.to_s; end
8
+ ld = lambda { @s.to_s }
9
+ cb = Callback &ld
10
+ c2 = Callback( @s, :to_s )
11
+ rb = RubyCallback { @s.to_s }
12
+ farm = @s.callback(:to_s)
13
+
14
+ tests = 100_000
15
+ puts "# Calling"
16
+ Benchmark.bmbm do |results|
17
+ results.report("methback:") { tests.times { me } }
18
+ results.report("lambdabk:") { tests.times { ld.call } }
19
+ results.report("callback:") { tests.times { cb.call } }
20
+ results.report("callbak2:") { tests.times { c2.call } }
21
+ results.report("rubyback:") { tests.times { rb.call } }
22
+ results.report("farm:") { tests.times { farm.call } }
23
+ end
data/callback.gemspec ADDED
@@ -0,0 +1,26 @@
1
+ Gem::Specification.new do |s|
2
+ s.name = "callback"
3
+ s.version = "1.0.0"
4
+ s.date = "2009-08-22"
5
+ s.summary = "Native MRI callback"
6
+ s.email = "lourens@methodmissing.com"
7
+ s.homepage = "http://github.com/methodmissing/callback"
8
+ s.description = "Simple native Callback object for Ruby MRI (1.8.{6,7} and 1.9.2)"
9
+ s.has_rdoc = true
10
+ s.authors = ["Lourens Naudé (methodmissing)","James Tucker (raggi)"]
11
+ s.platform = Gem::Platform::RUBY
12
+ s.files = %w[
13
+ README
14
+ Rakefile
15
+ bench/bench.rb
16
+ bench/pure_ruby_cb.rb
17
+ bench/raggi_bench.rb
18
+ ext/callback/extconf.rb
19
+ ext/callback/callback.c
20
+ lib/callback.rb
21
+ callback.gemspec
22
+ ] + Dir.glob('test/*')
23
+ s.rdoc_options = ["--main", "README"]
24
+ s.extra_rdoc_files = ["README"]
25
+ s.extensions << "ext/callback/extconf.rb"
26
+ end
@@ -0,0 +1,95 @@
1
+ #include "ruby.h"
2
+
3
+ typedef struct {
4
+ VALUE object;
5
+ ID method;
6
+ } RCallback;
7
+
8
+ #define GetCallbackStruct(obj) (Check_Type(obj, T_DATA), (RCallback*)DATA_PTR(obj))
9
+
10
+ VALUE rb_cCallback;
11
+ static ID id_call;
12
+
13
+ static void mark_callback(RCallback* cb)
14
+ {
15
+ rb_gc_mark(cb->object);
16
+ }
17
+
18
+ static void free_callback(RCallback* cb)
19
+ {
20
+ xfree(cb);
21
+ }
22
+
23
+ static VALUE callback_alloc _((VALUE));
24
+ static VALUE
25
+ callback_alloc( VALUE klass )
26
+ {
27
+ VALUE cb;
28
+ RCallback* cbs;
29
+ cb = Data_Make_Struct(klass, RCallback, mark_callback, free_callback, cbs);
30
+ cbs->object = Qnil;
31
+ cbs->method = 0;
32
+
33
+ return cb;
34
+ }
35
+
36
+ static VALUE
37
+ rb_callback_new()
38
+ {
39
+ return callback_alloc(rb_cCallback);
40
+ }
41
+
42
+ static VALUE rb_callback_initialize( int argc, VALUE *argv, VALUE cb )
43
+ {
44
+ VALUE object;
45
+ VALUE method;
46
+ RCallback* cbs = GetCallbackStruct(cb);
47
+
48
+ if (rb_block_given_p()) {
49
+ if (argc == 1) rb_raise(rb_eArgError, "wrong number of arguments");
50
+ cbs->object = rb_block_proc();
51
+ cbs->method = id_call;
52
+ }else {
53
+ rb_scan_args(argc, argv, "02", &object, &method);
54
+ cbs->object = object;
55
+ cbs->method = rb_to_id(method);
56
+ }
57
+
58
+ OBJ_FREEZE(cb);
59
+ return cb;
60
+ }
61
+
62
+ static VALUE rb_callback_call( VALUE cb, VALUE args )
63
+ {
64
+ RCallback* cbs = GetCallbackStruct(cb);
65
+ return rb_apply(cbs->object, cbs->method, args);
66
+ }
67
+
68
+ static VALUE rb_f_callback( int argc, VALUE *argv )
69
+ {
70
+ return rb_callback_initialize( argc, argv, rb_callback_new() );
71
+ }
72
+
73
+ static VALUE
74
+ rb_obj_callback( VALUE obj, VALUE mid)
75
+ {
76
+ VALUE args[2];
77
+ args[0] = obj;
78
+ args[1] = mid;
79
+ return rb_f_callback( 2, (VALUE *)args );
80
+ }
81
+
82
+ void
83
+ Init_callback()
84
+ {
85
+ id_call = rb_intern("call");
86
+
87
+ rb_cCallback = rb_define_class("Callback", rb_cObject);
88
+ rb_define_alloc_func(rb_cCallback, callback_alloc);
89
+
90
+ rb_define_method(rb_cCallback,"initialize", rb_callback_initialize, -1);
91
+ rb_define_method(rb_cCallback,"call", rb_callback_call, -2);
92
+
93
+ rb_define_global_function("Callback", rb_f_callback, -1);
94
+ rb_define_method(rb_mKernel, "callback", rb_obj_callback, 1);
95
+ }
@@ -0,0 +1,5 @@
1
+ require 'mkmf'
2
+
3
+ dir_config('callback')
4
+
5
+ create_makefile('callback')
data/lib/callback.rb ADDED
@@ -0,0 +1 @@
1
+ # stubbed
metadata ADDED
@@ -0,0 +1,64 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: methodmissing-callback
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - "Lourens Naud\xC3\xA9 (methodmissing)"
8
+ - James Tucker (raggi)
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+
13
+ date: 2009-08-22 00:00:00 -07:00
14
+ default_executable:
15
+ dependencies: []
16
+
17
+ description: Simple native Callback object for Ruby MRI (1.8.{6,7} and 1.9.2)
18
+ email: lourens@methodmissing.com
19
+ executables: []
20
+
21
+ extensions:
22
+ - ext/callback/extconf.rb
23
+ extra_rdoc_files:
24
+ - README
25
+ files:
26
+ - README
27
+ - Rakefile
28
+ - bench/bench.rb
29
+ - bench/pure_ruby_cb.rb
30
+ - bench/raggi_bench.rb
31
+ - ext/callback/extconf.rb
32
+ - ext/callback/callback.c
33
+ - lib/callback.rb
34
+ - callback.gemspec
35
+ has_rdoc: true
36
+ homepage: http://github.com/methodmissing/callback
37
+ licenses:
38
+ post_install_message:
39
+ rdoc_options:
40
+ - --main
41
+ - README
42
+ require_paths:
43
+ - lib
44
+ required_ruby_version: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - ">="
47
+ - !ruby/object:Gem::Version
48
+ version: "0"
49
+ version:
50
+ required_rubygems_version: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: "0"
55
+ version:
56
+ requirements: []
57
+
58
+ rubyforge_project:
59
+ rubygems_version: 1.3.5
60
+ signing_key:
61
+ specification_version: 2
62
+ summary: Native MRI callback
63
+ test_files: []
64
+