cb 1.0.1
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 +42 -0
- data/Rakefile +171 -0
- data/bench/bench.rb +22 -0
- data/bench/pure_ruby_cb.rb +17 -0
- data/bench/raggi_bench.rb +24 -0
- data/ext/mri_callback/extconf.rb +5 -0
- data/ext/mri_callback/mri_callback.c +85 -0
- data/lib/cb.rb +72 -0
- data/test/test_cb.rb +78 -0
- metadata +65 -0
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/cb
|
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,171 @@
|
|
1
|
+
#!/usr/bin/env rake
|
2
|
+
require 'rake/testtask'
|
3
|
+
require 'rake/clean'
|
4
|
+
|
5
|
+
def spec(file = Dir['*.gemspec'].first)
|
6
|
+
@spec ||=
|
7
|
+
begin
|
8
|
+
require 'rubygems/specification'
|
9
|
+
Thread.abort_on_exception = true
|
10
|
+
data = File.read(file)
|
11
|
+
spec = nil
|
12
|
+
Thread.new { spec = eval("$SAFE = 3\n#{data}") }.join
|
13
|
+
spec.instance_variable_set(:@filename, file)
|
14
|
+
def spec.filename; @filename; end
|
15
|
+
spec
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def manifest; @manifest ||= `git ls-files`.split("\n").reject{|s|s=~/\.gemspec$|\.gitignore$/}; end
|
20
|
+
|
21
|
+
@gem_package_task_type = begin
|
22
|
+
require 'rubygems/package_task'
|
23
|
+
Gem::PackageTask
|
24
|
+
rescue LoadError
|
25
|
+
require 'rake/gempackagetask'
|
26
|
+
Rake::GemPackageTask
|
27
|
+
end
|
28
|
+
def gem_task; @gem_task ||= @gem_package_task_type.new(spec); end
|
29
|
+
gem_task.define
|
30
|
+
Rake::Task[:clobber].enhance [:clobber_package]
|
31
|
+
|
32
|
+
rdoc_task_type = begin
|
33
|
+
require 'rdoc/task'
|
34
|
+
RDoc::Task
|
35
|
+
rescue LoadError
|
36
|
+
require 'rake/rdoctask'
|
37
|
+
Rake::RDocTask
|
38
|
+
end
|
39
|
+
df = begin; require 'rdoc/generator/darkfish'; true; rescue LoadError; end
|
40
|
+
rdtask = rdoc_task_type.new do |rd|
|
41
|
+
rd.title = spec.name
|
42
|
+
rd.main = spec.extra_rdoc_files.first
|
43
|
+
lib_rexp = spec.require_paths.map { |p| Regexp.escape p }.join('|')
|
44
|
+
rd.rdoc_files.include(*manifest.grep(/^(?:#{lib_rexp})/))
|
45
|
+
rd.rdoc_files.include(*spec.extra_rdoc_files)
|
46
|
+
rd.template = 'darkfish' if df
|
47
|
+
end
|
48
|
+
|
49
|
+
Rake::Task[:clobber].enhance [:clobber_rdoc]
|
50
|
+
|
51
|
+
desc 'Generate and open documentation'
|
52
|
+
task :docs => :rdoc do
|
53
|
+
path = rdtask.send :rdoc_target
|
54
|
+
case RUBY_PLATFORM
|
55
|
+
when /darwin/ ; sh "open #{path}"
|
56
|
+
when /mswin|mingw/ ; sh "start #{path}"
|
57
|
+
else
|
58
|
+
sh "firefox #{path}"
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
desc "Regenerate gemspec"
|
63
|
+
task :gemspec => spec.filename
|
64
|
+
|
65
|
+
task spec.filename do
|
66
|
+
spec.files = manifest
|
67
|
+
spec.test_files = FileList['{test,spec}/**/{test,spec}_*.rb']
|
68
|
+
open(spec.filename, 'w') { |w| w.write spec.to_ruby }
|
69
|
+
end
|
70
|
+
|
71
|
+
desc "Bump version from #{spec.version} to #{spec.version.to_s.succ}"
|
72
|
+
task :bump do
|
73
|
+
spec.version = spec.version.to_s.succ
|
74
|
+
end
|
75
|
+
|
76
|
+
desc "Tag version #{spec.version}"
|
77
|
+
task :tag do
|
78
|
+
tagged = Dir.new('.git/refs/tags').entries.include? spec.version.to_s
|
79
|
+
if tagged
|
80
|
+
warn "Tag #{spec.version} already exists"
|
81
|
+
else
|
82
|
+
# TODO release message in tag message
|
83
|
+
sh "git tag #{spec.version}"
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
if spec.rubyforge_project
|
88
|
+
require 'yaml'
|
89
|
+
require 'rake/contrib/sshpublisher'
|
90
|
+
desc "Publish rdoc to rubyforge"
|
91
|
+
task :publish => rdtask.name do
|
92
|
+
rf_cfg = File.expand_path '~/.rubyforge/user-config.yml'
|
93
|
+
host = "#{YAML.load_file(rf_cfg)['username']}@rubyforge.org"
|
94
|
+
remote_dir = "/var/www/gforge-projects/#{spec.rubyforge_project}/#{spec.name}/"
|
95
|
+
Rake::SshDirPublisher.new(host, remote_dir, rdtask.rdoc_dir).upload
|
96
|
+
end
|
97
|
+
|
98
|
+
desc "Release #{gem_task.gem_file} to rubyforge"
|
99
|
+
task :release => [:tag, :gem, :publish] do |t|
|
100
|
+
sh "rubyforge add_release #{spec.rubyforge_project} #{spec.name} #{spec.version} #{gem_task.package_dir}/#{gem_task.gem_file}"
|
101
|
+
end
|
102
|
+
else
|
103
|
+
warn "Cannot release to rubyforge - no rubyforge_project in gemspec"
|
104
|
+
end
|
105
|
+
|
106
|
+
CB_ROOT = 'ext/mri_callback'
|
107
|
+
|
108
|
+
desc 'Default: test'
|
109
|
+
task :default => :test
|
110
|
+
|
111
|
+
desc 'Run callback tests.'
|
112
|
+
Rake::TestTask.new(:test) do |t|
|
113
|
+
t.libs << CB_ROOT
|
114
|
+
t.pattern = 'test/test_*.rb'
|
115
|
+
t.verbose = true
|
116
|
+
end
|
117
|
+
task :test
|
118
|
+
|
119
|
+
namespace :build do
|
120
|
+
file "#{CB_ROOT}/mri_callback.c"
|
121
|
+
file "#{CB_ROOT}/extconf.rb"
|
122
|
+
file "#{CB_ROOT}/Makefile" => %W(#{CB_ROOT}/mri_callback.c #{CB_ROOT}/extconf.rb) do
|
123
|
+
Dir.chdir(CB_ROOT) do
|
124
|
+
ruby 'extconf.rb'
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
desc "generate makefile"
|
129
|
+
task :makefile => %W(#{CB_ROOT}/Makefile #{CB_ROOT}/mri_callback.c)
|
130
|
+
|
131
|
+
dlext = Config::CONFIG['DLEXT']
|
132
|
+
file "#{CB_ROOT}/mri_callback.#{dlext}" => %W(#{CB_ROOT}/Makefile #{CB_ROOT}/mri_callback.c) do
|
133
|
+
Dir.chdir(CB_ROOT) do
|
134
|
+
sh 'make' # TODO - is there a config for which make somewhere?
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
desc "compile callback extension"
|
139
|
+
task :compile => "#{CB_ROOT}/mri_callback.#{dlext}"
|
140
|
+
|
141
|
+
task :clean do
|
142
|
+
Dir.chdir(CB_ROOT) do
|
143
|
+
sh 'make clean'
|
144
|
+
end if File.exists?("#{CB_ROOT}/Makefile")
|
145
|
+
end
|
146
|
+
|
147
|
+
CLEAN.include("#{CB_ROOT}/Makefile")
|
148
|
+
CLEAN.include("#{CB_ROOT}/mri_callback.#{dlext}")
|
149
|
+
end
|
150
|
+
|
151
|
+
task :clean => %w(build:clean)
|
152
|
+
|
153
|
+
desc "compile"
|
154
|
+
task :build => %w(build:compile)
|
155
|
+
|
156
|
+
task :install do |t|
|
157
|
+
Dir.chdir(CB_ROOT) do
|
158
|
+
sh 'sudo make install'
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
desc "clean build install"
|
163
|
+
task :setup => %w(clean build install)
|
164
|
+
|
165
|
+
desc "run benchmarks"
|
166
|
+
task :bench do |t|
|
167
|
+
ruby "-Ilib:ext/mri_callback:bench", "bench/bench.rb"
|
168
|
+
puts
|
169
|
+
ruby "-Ilib:ext/mri_callback:bench", "bench/raggi_bench.rb"
|
170
|
+
end
|
171
|
+
task :bench
|
data/bench/bench.rb
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
require "benchmark"
|
2
|
+
require "callback"
|
3
|
+
require "pure_ruby_cb"
|
4
|
+
|
5
|
+
class Object
|
6
|
+
public :method
|
7
|
+
end
|
8
|
+
|
9
|
+
def meth
|
10
|
+
'hai'
|
11
|
+
end
|
12
|
+
|
13
|
+
TESTS = 10_000
|
14
|
+
Benchmark.bmbm do |results|
|
15
|
+
results.report("Method object:") { TESTS.times { method(:meth).call } }
|
16
|
+
results.report("Callback{ 'hai' }.call") { TESTS.times { Callback{ 'hai' }.call } }
|
17
|
+
results.report("RubyCallback{ 'hai' }.call") { TESTS.times { RubyCallback{ 'hai' }.call } }
|
18
|
+
results.report("Callback( 'bai', :to_s ).call") { TESTS.times { Callback( 'bai', :to_s ).call } }
|
19
|
+
results.report("RubyCallback( 'bai', :to_s ).call") { TESTS.times { RubyCallback( 'bai', :to_s ).call } }
|
20
|
+
results.report("Callback( 'bai', :gsub ).call( 'b', 'h' )") { TESTS.times { Callback( 'bai', :gsub ).call( 'b', 'h' ) } }
|
21
|
+
results.report("RubyCallback( 'bai', :gsub ).call( 'b', 'h' )") { TESTS.times { RubyCallback( 'bai', :gsub).call( 'b', 'h' ) } }
|
22
|
+
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,24 @@
|
|
1
|
+
require "benchmark"
|
2
|
+
require "callback"
|
3
|
+
require "pure_ruby_cb"
|
4
|
+
|
5
|
+
@s = 'foo'
|
6
|
+
def me; @s.to_s; end
|
7
|
+
ld = lambda { @s.to_s }
|
8
|
+
cb = Callback &ld
|
9
|
+
c2 = Callback( @s, :to_s )
|
10
|
+
rb = RubyCallback { @s.to_s }
|
11
|
+
farm = @s.callback(:to_s)
|
12
|
+
meth = @s.send(:method, :to_s)
|
13
|
+
|
14
|
+
tests = 100_000
|
15
|
+
puts "# Calling"
|
16
|
+
Benchmark.bmbm do |results|
|
17
|
+
results.report("method invoked:") { tests.times { me } }
|
18
|
+
results.report("ruby method obj:") { tests.times { meth.call } }
|
19
|
+
results.report("object native callback:") { tests.times { farm.call } }
|
20
|
+
results.report("callback native:") { tests.times { c2.call } }
|
21
|
+
results.report("callback block:") { tests.times { cb.call } }
|
22
|
+
results.report("pure ruby callback:") { tests.times { rb.call } }
|
23
|
+
results.report("lambda:") { tests.times { ld.call } }
|
24
|
+
end
|
@@ -0,0 +1,85 @@
|
|
1
|
+
#include "ruby.h"
|
2
|
+
|
3
|
+
#ifndef RSTRING_PTR
|
4
|
+
#define RSTRING_PTR(obj) RSTRING(obj)->ptr
|
5
|
+
#endif
|
6
|
+
|
7
|
+
typedef struct {
|
8
|
+
VALUE object;
|
9
|
+
ID method;
|
10
|
+
} RCallback;
|
11
|
+
|
12
|
+
#define GetCallbackStruct(obj) (Check_Type(obj, T_DATA), (RCallback*)DATA_PTR(obj))
|
13
|
+
|
14
|
+
VALUE rb_cCallback;
|
15
|
+
static ID id_call;
|
16
|
+
|
17
|
+
static void mark_mri_callback(RCallback* cb)
|
18
|
+
{
|
19
|
+
rb_gc_mark(cb->object);
|
20
|
+
}
|
21
|
+
|
22
|
+
static void free_mri_callback(RCallback* cb)
|
23
|
+
{
|
24
|
+
xfree(cb);
|
25
|
+
}
|
26
|
+
|
27
|
+
static VALUE callback_alloc _((VALUE));
|
28
|
+
static VALUE
|
29
|
+
callback_alloc( VALUE klass )
|
30
|
+
{
|
31
|
+
VALUE cb;
|
32
|
+
RCallback* cbs;
|
33
|
+
cb = Data_Make_Struct(klass, RCallback, mark_mri_callback, free_mri_callback, cbs);
|
34
|
+
cbs->object = Qnil;
|
35
|
+
cbs->method = 0;
|
36
|
+
|
37
|
+
return cb;
|
38
|
+
}
|
39
|
+
|
40
|
+
static VALUE
|
41
|
+
rb_mri_callback_new()
|
42
|
+
{
|
43
|
+
return callback_alloc(rb_cCallback);
|
44
|
+
}
|
45
|
+
|
46
|
+
static VALUE rb_mri_callback_initialize( int argc, VALUE *argv, VALUE cb )
|
47
|
+
{
|
48
|
+
VALUE object;
|
49
|
+
VALUE method;
|
50
|
+
ID meth;
|
51
|
+
RCallback* cbs = GetCallbackStruct(cb);
|
52
|
+
|
53
|
+
if (rb_block_given_p()) {
|
54
|
+
if (argc == 1) rb_raise(rb_eArgError, "wrong number of arguments");
|
55
|
+
cbs->object = rb_block_proc();
|
56
|
+
cbs->method = id_call;
|
57
|
+
}else {
|
58
|
+
rb_scan_args(argc, argv, "02", &object, &method);
|
59
|
+
cbs->object = object;
|
60
|
+
meth = rb_to_id(method);
|
61
|
+
if (!rb_respond_to(object,meth)) rb_raise(rb_eArgError, "object does not respond to %s", RSTRING_PTR(rb_obj_as_string(method)));
|
62
|
+
cbs->method = meth;
|
63
|
+
}
|
64
|
+
|
65
|
+
OBJ_FREEZE(cb);
|
66
|
+
return cb;
|
67
|
+
}
|
68
|
+
|
69
|
+
static VALUE rb_mri_callback_call( VALUE cb, VALUE args )
|
70
|
+
{
|
71
|
+
RCallback* cbs = GetCallbackStruct(cb);
|
72
|
+
return rb_apply(cbs->object, cbs->method, args);
|
73
|
+
}
|
74
|
+
|
75
|
+
void
|
76
|
+
Init_mri_callback()
|
77
|
+
{
|
78
|
+
id_call = rb_intern("call");
|
79
|
+
|
80
|
+
rb_cCallback = rb_define_class("Callback", rb_cObject);
|
81
|
+
rb_define_alloc_func(rb_cCallback, callback_alloc);
|
82
|
+
|
83
|
+
rb_define_method(rb_cCallback,"initialize", rb_mri_callback_initialize, -1);
|
84
|
+
rb_define_method(rb_cCallback,"call", rb_mri_callback_call, -2);
|
85
|
+
}
|
data/lib/cb.rb
ADDED
@@ -0,0 +1,72 @@
|
|
1
|
+
begin
|
2
|
+
require 'mri_callback'
|
3
|
+
rescue LoadError
|
4
|
+
end
|
5
|
+
|
6
|
+
# A simple __send__ based callback implementation, simply Object Orients
|
7
|
+
# something equivalent to:
|
8
|
+
#
|
9
|
+
# lambda { |*args| object.__send__ method, *args }
|
10
|
+
class Callback
|
11
|
+
class << self; attr_reader :extension_loaded; end
|
12
|
+
|
13
|
+
begin
|
14
|
+
cb = new(self, :instance_variable_set)
|
15
|
+
cb.respond_to?(:call) && cb.call(:@extension_loaded, true)
|
16
|
+
rescue ArgumentError
|
17
|
+
@extension_loaded = false
|
18
|
+
end
|
19
|
+
|
20
|
+
unless @extension_loaded
|
21
|
+
warn "Using pure ruby Callback"
|
22
|
+
def initialize(object, method)
|
23
|
+
@object, @method = object, method
|
24
|
+
end
|
25
|
+
|
26
|
+
def call(*args)
|
27
|
+
@object.__send__(@method, *args)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
# A quick monkey patch providing a public equivalent of the #method private
|
33
|
+
# method aliased to #callback. This is intended for use as a persistent
|
34
|
+
# callback object. It should be noted that using Method objects under MRI has
|
35
|
+
# in the past lead to user induced leaks. One must be careful when using it.
|
36
|
+
class Object
|
37
|
+
alias callback method
|
38
|
+
|
39
|
+
# Allow users to call object.callback(:method_name) to grab a Method object.
|
40
|
+
public :callback
|
41
|
+
end
|
42
|
+
|
43
|
+
# Utility method for coercing arguments to an object that responds to #call
|
44
|
+
# Accepts an object and a method name to send to, or a block, or an object
|
45
|
+
# that responds to call.
|
46
|
+
#
|
47
|
+
# cb = Callback{ |msg| puts(msg) }
|
48
|
+
# cb.call('hello world')
|
49
|
+
#
|
50
|
+
# cb = Callback(Object, :puts)
|
51
|
+
# cb.call('hello world')
|
52
|
+
#
|
53
|
+
# cb = Callback(proc{ |msg| puts(msg) })
|
54
|
+
# cb.call('hello world')
|
55
|
+
module Kernel
|
56
|
+
def Callback(object = nil, method = nil, &blk)
|
57
|
+
if object && method
|
58
|
+
Callback.new(object, method)
|
59
|
+
else
|
60
|
+
if object.respond_to? :call
|
61
|
+
object
|
62
|
+
else
|
63
|
+
if object && blk || blk.nil?
|
64
|
+
raise(ArgumentError, "Callback required an object responding to #call or an object and a method, or a block")
|
65
|
+
else
|
66
|
+
blk
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
private :Callback
|
72
|
+
end
|
data/test/test_cb.rb
ADDED
@@ -0,0 +1,78 @@
|
|
1
|
+
require "test/unit"
|
2
|
+
require "cb"
|
3
|
+
|
4
|
+
class TestCallbackPureRuby < Test::Unit::TestCase
|
5
|
+
def test_Callback_with_lambda
|
6
|
+
ran = false
|
7
|
+
l = lambda { ran = true }
|
8
|
+
Callback(l).call
|
9
|
+
assert ran
|
10
|
+
end
|
11
|
+
|
12
|
+
def cb
|
13
|
+
@ran = true
|
14
|
+
end
|
15
|
+
|
16
|
+
def test_Callback_with_object_and_method
|
17
|
+
@ran = false
|
18
|
+
Callback(self, :cb).call
|
19
|
+
assert @ran
|
20
|
+
end
|
21
|
+
|
22
|
+
def test_Callback_with_block
|
23
|
+
ran = false
|
24
|
+
Callback { ran = true }.call
|
25
|
+
assert ran
|
26
|
+
end
|
27
|
+
|
28
|
+
def test_Callback_with_no_arguments
|
29
|
+
assert_raises(ArgumentError) do
|
30
|
+
Callback()
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def test_Object_callback
|
35
|
+
@ran = false
|
36
|
+
self.callback(:cb).call
|
37
|
+
assert @ran
|
38
|
+
end
|
39
|
+
|
40
|
+
def test_block
|
41
|
+
cb = Callback{ 'hai' }
|
42
|
+
assert_equal 'hai', cb.call
|
43
|
+
end
|
44
|
+
|
45
|
+
def test_init_object_call_with_no_args
|
46
|
+
cb = Callback( 'bai', :to_s )
|
47
|
+
assert_equal 'bai', cb.call
|
48
|
+
end
|
49
|
+
|
50
|
+
def test_init_object_call_with_args
|
51
|
+
cb = Callback( 'bai', :gsub )
|
52
|
+
assert_equal 'hai', cb.call( 'b', 'h' )
|
53
|
+
end
|
54
|
+
|
55
|
+
def test_many_calls
|
56
|
+
cb = Callback { :foo }
|
57
|
+
100_000.times { cb.call }
|
58
|
+
end
|
59
|
+
|
60
|
+
def test_arguments
|
61
|
+
assert_raises ArgumentError do
|
62
|
+
Callback( 'hai' ){}
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def test_farmed_from_object
|
67
|
+
cb = 'hai'.callback(:to_s)
|
68
|
+
assert_equal 'hai', cb.call
|
69
|
+
ocb = 'bai'.callback(:gsub)
|
70
|
+
assert_equal 'hai', ocb.call('b', 'h')
|
71
|
+
end
|
72
|
+
|
73
|
+
def test_invalid_method
|
74
|
+
assert_raises NameError do
|
75
|
+
'str'.callback(:undefined)
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
metadata
ADDED
@@ -0,0 +1,65 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: cb
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.1
|
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 +01: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/mri_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/mri_callback/extconf.rb
|
32
|
+
- ext/mri_callback/mri_callback.c
|
33
|
+
- lib/cb.rb
|
34
|
+
- test/test_cb.rb
|
35
|
+
has_rdoc: true
|
36
|
+
homepage: http://github.com/methodmissing/cb
|
37
|
+
licenses: []
|
38
|
+
|
39
|
+
post_install_message:
|
40
|
+
rdoc_options:
|
41
|
+
- --main
|
42
|
+
- README
|
43
|
+
require_paths:
|
44
|
+
- lib
|
45
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
46
|
+
requirements:
|
47
|
+
- - ">="
|
48
|
+
- !ruby/object:Gem::Version
|
49
|
+
version: "0"
|
50
|
+
version:
|
51
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
52
|
+
requirements:
|
53
|
+
- - ">="
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
version: "0"
|
56
|
+
version:
|
57
|
+
requirements: []
|
58
|
+
|
59
|
+
rubyforge_project:
|
60
|
+
rubygems_version: 1.3.5
|
61
|
+
signing_key:
|
62
|
+
specification_version: 3
|
63
|
+
summary: Native MRI callback
|
64
|
+
test_files:
|
65
|
+
- test/test_cb.rb
|