event_hook 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.tar.gz.sig +3 -0
- data/.autotest +23 -0
- data/History.txt +6 -0
- data/Manifest.txt +9 -0
- data/README.txt +64 -0
- data/Rakefile +15 -0
- data/bin/event_hook +3 -0
- data/demo.rb +58 -0
- data/lib/event_hook.rb +109 -0
- data/test/test_event_hook.rb +51 -0
- metadata +118 -0
- metadata.gz.sig +0 -0
data.tar.gz.sig
ADDED
data/.autotest
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
# -*- ruby -*-
|
2
|
+
|
3
|
+
require 'autotest/restart'
|
4
|
+
|
5
|
+
# Autotest.add_hook :initialize do |at|
|
6
|
+
# at.extra_files << "../some/external/dependency.rb"
|
7
|
+
#
|
8
|
+
# at.libs << ":../some/external"
|
9
|
+
#
|
10
|
+
# at.add_exception 'vendor'
|
11
|
+
#
|
12
|
+
# at.add_mapping(/dependency.rb/) do |f, _|
|
13
|
+
# at.files_matching(/test_.*rb$/)
|
14
|
+
# end
|
15
|
+
#
|
16
|
+
# %w(TestA TestB).each do |klass|
|
17
|
+
# at.extra_class_map[klass] = "test/test_misc.rb"
|
18
|
+
# end
|
19
|
+
# end
|
20
|
+
|
21
|
+
# Autotest.add_hook :run_command do |at|
|
22
|
+
# system "rake build"
|
23
|
+
# end
|
data/History.txt
ADDED
data/Manifest.txt
ADDED
data/README.txt
ADDED
@@ -0,0 +1,64 @@
|
|
1
|
+
= event_hook
|
2
|
+
|
3
|
+
* http://rubyforge.org/projects/seattlerb
|
4
|
+
|
5
|
+
== DESCRIPTION:
|
6
|
+
|
7
|
+
Wraps rb_add_event_hook so you can write fast ruby event hook
|
8
|
+
processors w/o the speed penalty that comes with set_trace_func (sooo
|
9
|
+
sloooow!). Calls back into ruby so you don't have to write C.
|
10
|
+
|
11
|
+
% ruby demo.rb
|
12
|
+
# of iterations = 1000000
|
13
|
+
user system total real
|
14
|
+
null_time 0.120000 0.000000 0.120000 ( 0.125279)
|
15
|
+
ruby time 0.560000 0.000000 0.560000 ( 0.562834)
|
16
|
+
event hook 3.160000 0.010000 3.170000 ( 3.175361)
|
17
|
+
set_trace_func 34.530000 0.100000 34.630000 ( 34.942785)
|
18
|
+
|
19
|
+
== FEATURES/PROBLEMS:
|
20
|
+
|
21
|
+
* Simple subclass design. Override ::process and you're off.
|
22
|
+
* Filters on calls/returns to not bog down on extraneous events.
|
23
|
+
* Not sure why process needs to be a class method. Will fix eventually.
|
24
|
+
|
25
|
+
== SYNOPSIS:
|
26
|
+
|
27
|
+
class StupidTracer < EventHook
|
28
|
+
self.process(*args)
|
29
|
+
p args
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
== REQUIREMENTS:
|
34
|
+
|
35
|
+
* RubyInline
|
36
|
+
|
37
|
+
== INSTALL:
|
38
|
+
|
39
|
+
* sudo gem install event_hook
|
40
|
+
|
41
|
+
== LICENSE:
|
42
|
+
|
43
|
+
(The MIT License)
|
44
|
+
|
45
|
+
Copyright (c) 2009 Ryan Davis, Seattle.rb
|
46
|
+
|
47
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
48
|
+
a copy of this software and associated documentation files (the
|
49
|
+
'Software'), to deal in the Software without restriction, including
|
50
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
51
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
52
|
+
permit persons to whom the Software is furnished to do so, subject to
|
53
|
+
the following conditions:
|
54
|
+
|
55
|
+
The above copyright notice and this permission notice shall be
|
56
|
+
included in all copies or substantial portions of the Software.
|
57
|
+
|
58
|
+
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
59
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
60
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
61
|
+
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
62
|
+
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
63
|
+
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
64
|
+
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/Rakefile
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
# -*- ruby -*-
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
require 'hoe'
|
5
|
+
require './lib/event_hook.rb'
|
6
|
+
|
7
|
+
Hoe.new('event_hook', EventHook::VERSION) do |p|
|
8
|
+
p.rubyforge_name = 'seattlerb'
|
9
|
+
|
10
|
+
p.developer('Ryan Davis', 'ryand-ruby@zenspider.com')
|
11
|
+
|
12
|
+
p.extra_deps << 'RubyInline'
|
13
|
+
end
|
14
|
+
|
15
|
+
# vim: syntax=Ruby
|
data/bin/event_hook
ADDED
data/demo.rb
ADDED
@@ -0,0 +1,58 @@
|
|
1
|
+
#!/usr/bin/env ruby -w
|
2
|
+
|
3
|
+
require 'benchmark'
|
4
|
+
|
5
|
+
$: << 'lib'
|
6
|
+
require 'rubygems'
|
7
|
+
require 'event_hook'
|
8
|
+
|
9
|
+
class Demo < EventHook
|
10
|
+
def self.process(*ignore)
|
11
|
+
end
|
12
|
+
|
13
|
+
def call_a_method
|
14
|
+
a_method
|
15
|
+
end
|
16
|
+
|
17
|
+
def a_method
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
SET_TRACE_FUNC_PROC = proc { |e, f, l, m, b, c|
|
22
|
+
# do nothing
|
23
|
+
}
|
24
|
+
|
25
|
+
max = (ARGV.shift || 1_000_000).to_i
|
26
|
+
|
27
|
+
demo = Demo.instance
|
28
|
+
|
29
|
+
puts "# of iterations = #{max}"
|
30
|
+
Benchmark::bm(20) do |x|
|
31
|
+
x.report("null_time") do
|
32
|
+
for i in 0..max do
|
33
|
+
# do nothing
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
x.report("ruby time") do
|
38
|
+
for i in 0..max do
|
39
|
+
demo.call_a_method
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
Demo.start_hook
|
44
|
+
x.report("event hook") do
|
45
|
+
for i in 0..max do
|
46
|
+
demo.call_a_method
|
47
|
+
end
|
48
|
+
end
|
49
|
+
Demo.stop_hook
|
50
|
+
|
51
|
+
set_trace_func SET_TRACE_FUNC_PROC
|
52
|
+
x.report("set_trace_func") do
|
53
|
+
for i in 0..max do
|
54
|
+
demo.call_a_method
|
55
|
+
end
|
56
|
+
end
|
57
|
+
set_trace_func nil
|
58
|
+
end
|
data/lib/event_hook.rb
ADDED
@@ -0,0 +1,109 @@
|
|
1
|
+
require 'inline'
|
2
|
+
require 'singleton'
|
3
|
+
|
4
|
+
class EventHook
|
5
|
+
VERSION = '1.0.0'
|
6
|
+
|
7
|
+
include Singleton
|
8
|
+
|
9
|
+
NONE = 0x00
|
10
|
+
LINE = 0x01
|
11
|
+
CLASS = 0x02
|
12
|
+
NND = 0x04
|
13
|
+
CALL = 0x08
|
14
|
+
RETURN = 0x10
|
15
|
+
CCALL = 0x20
|
16
|
+
CRETURN = 0x40
|
17
|
+
RAISE = 0x80
|
18
|
+
ALL = 0xff
|
19
|
+
|
20
|
+
##
|
21
|
+
# Ruby events that EventHook notifies you about.
|
22
|
+
|
23
|
+
EVENTS = {
|
24
|
+
LINE => :line,
|
25
|
+
CLASS => :class,
|
26
|
+
NND => :end,
|
27
|
+
CALL => :call,
|
28
|
+
RETURN => :return,
|
29
|
+
CCALL => :ccall,
|
30
|
+
CRETURN => :creturn,
|
31
|
+
RAISE => :raise,
|
32
|
+
}
|
33
|
+
|
34
|
+
def self.start_hook
|
35
|
+
self.instance.add_event_hook
|
36
|
+
end
|
37
|
+
|
38
|
+
def self.stop_hook
|
39
|
+
self.instance.remove_event_hook
|
40
|
+
end
|
41
|
+
|
42
|
+
##
|
43
|
+
# Redefine me in a subclass. +args+ is [event_id, self, method, class].
|
44
|
+
|
45
|
+
def self.process(*args)
|
46
|
+
raise NotImplementedError, "subclass responsibility"
|
47
|
+
end
|
48
|
+
|
49
|
+
inline(:C) do |builder|
|
50
|
+
builder.add_type_converter("rb_event_t", '', '')
|
51
|
+
builder.add_type_converter("ID", '', '')
|
52
|
+
builder.add_type_converter("NODE *", '', '')
|
53
|
+
|
54
|
+
builder.include '<time.h>'
|
55
|
+
builder.include '"ruby.h"'
|
56
|
+
builder.include '"node.h"'
|
57
|
+
|
58
|
+
builder.prefix <<-'EOF'
|
59
|
+
static VALUE event_hook_klass = Qnil;
|
60
|
+
static ID method = 0;
|
61
|
+
static int in_event_hook = 0;
|
62
|
+
static VALUE argv[4];
|
63
|
+
EOF
|
64
|
+
|
65
|
+
builder.c_raw <<-'EOF'
|
66
|
+
static void
|
67
|
+
event_hook(rb_event_t event, NODE *node, VALUE self, ID mid, VALUE klass) {
|
68
|
+
if (in_event_hook) return;
|
69
|
+
if (mid == ID_ALLOCATOR) return;
|
70
|
+
|
71
|
+
in_event_hook++;
|
72
|
+
|
73
|
+
if (NIL_P(event_hook_klass)) event_hook_klass = self;
|
74
|
+
if (method == 0) method = rb_intern("process");
|
75
|
+
|
76
|
+
if (klass) {
|
77
|
+
if (TYPE(klass) == T_ICLASS) {
|
78
|
+
klass = RBASIC(klass)->klass;
|
79
|
+
} else if (FL_TEST(klass, FL_SINGLETON)) {
|
80
|
+
klass = self;
|
81
|
+
}
|
82
|
+
}
|
83
|
+
|
84
|
+
argv[0] = UINT2NUM(event);
|
85
|
+
argv[1] = self;
|
86
|
+
argv[2] = ID2SYM(mid);
|
87
|
+
argv[3] = klass;
|
88
|
+
|
89
|
+
rb_funcall2(event_hook_klass, method, 4, argv);
|
90
|
+
|
91
|
+
in_event_hook--;
|
92
|
+
}
|
93
|
+
EOF
|
94
|
+
|
95
|
+
builder.c <<-'EOF'
|
96
|
+
void add_event_hook() {
|
97
|
+
rb_add_event_hook(event_hook, RUBY_EVENT_CALL | RUBY_EVENT_RETURN |
|
98
|
+
RUBY_EVENT_C_CALL | RUBY_EVENT_C_RETURN);
|
99
|
+
}
|
100
|
+
EOF
|
101
|
+
|
102
|
+
builder.c <<-'EOF'
|
103
|
+
void remove_event_hook() {
|
104
|
+
rb_remove_event_hook(event_hook);
|
105
|
+
event_hook_klass = Qnil;
|
106
|
+
}
|
107
|
+
EOF
|
108
|
+
end
|
109
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
require "test/unit"
|
2
|
+
require "event_hook"
|
3
|
+
|
4
|
+
class Stupid < EventHook
|
5
|
+
@@log = []
|
6
|
+
|
7
|
+
def self.log
|
8
|
+
@@log
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.process(*a)
|
12
|
+
@@log << a
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
class TestEventHook < Test::Unit::TestCase
|
17
|
+
def method_1
|
18
|
+
method_2
|
19
|
+
end
|
20
|
+
|
21
|
+
def method_2
|
22
|
+
method_3
|
23
|
+
end
|
24
|
+
|
25
|
+
def method_3
|
26
|
+
end
|
27
|
+
|
28
|
+
def test_sanity
|
29
|
+
Stupid.start_hook
|
30
|
+
method_1
|
31
|
+
Stupid.stop_hook
|
32
|
+
|
33
|
+
actual = Stupid.log.map { |id, obj, meth, klass|
|
34
|
+
[EventHook::EVENTS[id], klass, meth]
|
35
|
+
}
|
36
|
+
|
37
|
+
expected = [[:return, Stupid, :start_hook],
|
38
|
+
[:call, TestEventHook, :method_1],
|
39
|
+
[:call, TestEventHook, :method_2],
|
40
|
+
[:call, TestEventHook, :method_3],
|
41
|
+
[:return, TestEventHook, :method_3],
|
42
|
+
[:return, TestEventHook, :method_2],
|
43
|
+
[:return, TestEventHook, :method_1],
|
44
|
+
[:call, Stupid, :stop_hook],
|
45
|
+
[:call, Stupid, :instance],
|
46
|
+
[:return, Stupid, :instance],
|
47
|
+
[:ccall, EventHook, :remove_event_hook]]
|
48
|
+
|
49
|
+
assert_equal expected, actual
|
50
|
+
end
|
51
|
+
end
|
metadata
ADDED
@@ -0,0 +1,118 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: event_hook
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Ryan Davis
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain:
|
11
|
+
- |
|
12
|
+
-----BEGIN CERTIFICATE-----
|
13
|
+
MIIDPjCCAiagAwIBAgIBADANBgkqhkiG9w0BAQUFADBFMRMwEQYDVQQDDApyeWFu
|
14
|
+
ZC1ydWJ5MRkwFwYKCZImiZPyLGQBGRYJemVuc3BpZGVyMRMwEQYKCZImiZPyLGQB
|
15
|
+
GRYDY29tMB4XDTA5MDMwNjE4NTMxNVoXDTEwMDMwNjE4NTMxNVowRTETMBEGA1UE
|
16
|
+
AwwKcnlhbmQtcnVieTEZMBcGCgmSJomT8ixkARkWCXplbnNwaWRlcjETMBEGCgmS
|
17
|
+
JomT8ixkARkWA2NvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALda
|
18
|
+
b9DCgK+627gPJkB6XfjZ1itoOQvpqH1EXScSaba9/S2VF22VYQbXU1xQXL/WzCkx
|
19
|
+
taCPaLmfYIaFcHHCSY4hYDJijRQkLxPeB3xbOfzfLoBDbjvx5JxgJxUjmGa7xhcT
|
20
|
+
oOvjtt5P8+GSK9zLzxQP0gVLS/D0FmoE44XuDr3iQkVS2ujU5zZL84mMNqNB1znh
|
21
|
+
GiadM9GHRaDiaxuX0cIUBj19T01mVE2iymf9I6bEsiayK/n6QujtyCbTWsAS9Rqt
|
22
|
+
qhtV7HJxNKuPj/JFH0D2cswvzznE/a5FOYO68g+YCuFi5L8wZuuM8zzdwjrWHqSV
|
23
|
+
gBEfoTEGr7Zii72cx+sCAwEAAaM5MDcwCQYDVR0TBAIwADALBgNVHQ8EBAMCBLAw
|
24
|
+
HQYDVR0OBBYEFEfFe9md/r/tj/Wmwpy+MI8d9k/hMA0GCSqGSIb3DQEBBQUAA4IB
|
25
|
+
AQAY59gYvDxqSqgC92nAP9P8dnGgfZgLxP237xS6XxFGJSghdz/nI6pusfCWKM8m
|
26
|
+
vzjjH2wUMSSf3tNudQ3rCGLf2epkcU13/rguI88wO6MrE0wi4ZqLQX+eZQFskJb/
|
27
|
+
w6x9W1ur8eR01s397LSMexySDBrJOh34cm2AlfKr/jokKCTwcM0OvVZnAutaovC0
|
28
|
+
l1SVZ0ecg88bsWHA0Yhh7NFxK1utWoIhtB6AFC/+trM0FQEB/jZkIS8SaNzn96Rl
|
29
|
+
n0sZEf77FLf5peR8TP/PtmIg7Cyqz23sLM4mCOoTGIy5OcZ8TdyiyINUHtb5ej/T
|
30
|
+
FBHgymkyj/AOSqKRIpXPhjC6
|
31
|
+
-----END CERTIFICATE-----
|
32
|
+
|
33
|
+
date: 2009-05-20 00:00:00 -07:00
|
34
|
+
default_executable:
|
35
|
+
dependencies:
|
36
|
+
- !ruby/object:Gem::Dependency
|
37
|
+
name: RubyInline
|
38
|
+
type: :runtime
|
39
|
+
version_requirement:
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
requirements:
|
42
|
+
- - ">="
|
43
|
+
- !ruby/object:Gem::Version
|
44
|
+
version: "0"
|
45
|
+
version:
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: hoe
|
48
|
+
type: :development
|
49
|
+
version_requirement:
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 1.12.2
|
55
|
+
version:
|
56
|
+
description: |-
|
57
|
+
Wraps rb_add_event_hook so you can write fast ruby event hook
|
58
|
+
processors w/o the speed penalty that comes with set_trace_func (sooo
|
59
|
+
sloooow!). Calls back into ruby so you don't have to write C.
|
60
|
+
|
61
|
+
% ruby demo.rb
|
62
|
+
# of iterations = 1000000
|
63
|
+
user system total real
|
64
|
+
null_time 0.120000 0.000000 0.120000 ( 0.125279)
|
65
|
+
ruby time 0.560000 0.000000 0.560000 ( 0.562834)
|
66
|
+
event hook 3.160000 0.010000 3.170000 ( 3.175361)
|
67
|
+
set_trace_func 34.530000 0.100000 34.630000 ( 34.942785)
|
68
|
+
email:
|
69
|
+
- ryand-ruby@zenspider.com
|
70
|
+
executables:
|
71
|
+
- event_hook
|
72
|
+
extensions: []
|
73
|
+
|
74
|
+
extra_rdoc_files:
|
75
|
+
- History.txt
|
76
|
+
- Manifest.txt
|
77
|
+
- README.txt
|
78
|
+
files:
|
79
|
+
- .autotest
|
80
|
+
- History.txt
|
81
|
+
- Manifest.txt
|
82
|
+
- README.txt
|
83
|
+
- Rakefile
|
84
|
+
- bin/event_hook
|
85
|
+
- demo.rb
|
86
|
+
- lib/event_hook.rb
|
87
|
+
- test/test_event_hook.rb
|
88
|
+
has_rdoc: true
|
89
|
+
homepage: http://rubyforge.org/projects/seattlerb
|
90
|
+
licenses: []
|
91
|
+
|
92
|
+
post_install_message:
|
93
|
+
rdoc_options:
|
94
|
+
- --main
|
95
|
+
- README.txt
|
96
|
+
require_paths:
|
97
|
+
- lib
|
98
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
99
|
+
requirements:
|
100
|
+
- - ">="
|
101
|
+
- !ruby/object:Gem::Version
|
102
|
+
version: "0"
|
103
|
+
version:
|
104
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
105
|
+
requirements:
|
106
|
+
- - ">="
|
107
|
+
- !ruby/object:Gem::Version
|
108
|
+
version: "0"
|
109
|
+
version:
|
110
|
+
requirements: []
|
111
|
+
|
112
|
+
rubyforge_project: seattlerb
|
113
|
+
rubygems_version: 1.3.2
|
114
|
+
signing_key:
|
115
|
+
specification_version: 3
|
116
|
+
summary: Wraps rb_add_event_hook so you can write fast ruby event hook processors w/o the speed penalty that comes with set_trace_func (sooo sloooow!)
|
117
|
+
test_files:
|
118
|
+
- test/test_event_hook.rb
|
metadata.gz.sig
ADDED
Binary file
|