eventable 0.1.2 → 0.1.3
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/.DS_Store +0 -0
- data/README.markdown +16 -1
- data/eventable.gemspec +6 -1
- data/example/example_output.txt +56 -0
- data/example/simple_output.txt +2 -0
- data/lib/.DS_Store +0 -0
- data/lib/eventable/eventable.rb +26 -26
- data/lib/eventable/version.rb +1 -1
- data/spec/.DS_Store +0 -0
- data/spec/eventable/eventable_spec.rb +70 -38
- data/vendor/.DS_Store +0 -0
- metadata +22 -5
data/.DS_Store
ADDED
Binary file
|
data/README.markdown
CHANGED
@@ -4,7 +4,7 @@ An incredibly simple way to add events to your classes.
|
|
4
4
|
|
5
5
|
##Description##
|
6
6
|
|
7
|
-
Provides an easy to use and understand event model. Other systems did way too much for my needs
|
7
|
+
Provides an easy to use and understand event model. Other systems did way too much for my needs: I didn't need to monitor network IO ports, I didn't want a central loop that polled IO, I just wanted a simple way to add real, non-polled events to a class and to register other classes to listen for those events.
|
8
8
|
|
9
9
|
If you want a simple way to add events to your classes without a bunch of other unrelated IO stuff this is the solution for you. (If you want to monitor IO events check out EventMachine)
|
10
10
|
|
@@ -16,6 +16,10 @@ Eventable will even automatically remove registered listeners when they get garb
|
|
16
16
|
|
17
17
|
Eventable also allows for more fine-grain control than Observable. You can register for specific events instead of just saying, "Hey, let me know when anything changes."
|
18
18
|
|
19
|
+
##Concurrency considerations##
|
20
|
+
|
21
|
+
Events and threads do not scale well past a certain point but that's OK; they aren't meant to. They are meant for fast, simple communication beteen processes not large distributed processes like serving websites on massive server farms. If you need a solution that scales well to large distributed systems check out the Actor concurrency model.
|
22
|
+
|
19
23
|
##Install##
|
20
24
|
|
21
25
|
`$ gem install eventable`
|
@@ -165,6 +169,17 @@ This example shows you how you might actually use it in a multi-threaded environ
|
|
165
169
|
|
166
170
|
##Version History##
|
167
171
|
|
172
|
+
**2011.06.28**
|
173
|
+
Ver: 0.1.3
|
174
|
+
|
175
|
+
Updates:
|
176
|
+
|
177
|
+
Callbacks are now threaded:
|
178
|
+
This patches one of the last concurrency issues; if a callback takes a long time or hangs it won't affect any other callbacks or events that need to fire.
|
179
|
+
|
180
|
+
It's your responsiblity to make sure your callback works, as long as it does the callback thread will go out of scope (unless you retain it) and everyone is happy.
|
181
|
+
|
182
|
+
**2011.06.17**
|
168
183
|
Ver: 0.1.2
|
169
184
|
|
170
185
|
Design updates/fixes:
|
data/eventable.gemspec
CHANGED
@@ -2,7 +2,8 @@
|
|
2
2
|
$:.push File.expand_path("../lib", __FILE__)
|
3
3
|
# Kludge for older RubyGems not handling unparsable dates gracefully
|
4
4
|
# (psych 1.2.0 gem wouldn't build on test system so we're stuck with syck)
|
5
|
-
YAML::ENGINE.yamler = 'syck'
|
5
|
+
YAML::ENGINE.yamler = 'syck'
|
6
|
+
|
6
7
|
require "rubygems"
|
7
8
|
require "eventable/version"
|
8
9
|
|
@@ -14,8 +15,12 @@ Gem::Specification.new do |s|
|
|
14
15
|
s.homepage = "http://mikbe.tk/projects#eventable"
|
15
16
|
s.summary = %q{An incredibly simple and easy to use event mixin module.}
|
16
17
|
s.description = %q{Provides an easy to use and understand event model. If you want a simple, light-weight way to add events to your classes this is the solution for you.}
|
18
|
+
s.license = 'MIT'
|
19
|
+
|
20
|
+
s.required_ruby_version = ">= 1.9.2"
|
17
21
|
|
18
22
|
s.add_development_dependency('rspec', "~>2.6")
|
23
|
+
s.add_development_dependency('bundler', "~>1.0")
|
19
24
|
|
20
25
|
s.files = `git ls-files`.split("\n")
|
21
26
|
s.test_files = `git ls-files -- {spec}/*`.split("\n")
|
@@ -0,0 +1,56 @@
|
|
1
|
+
[1] did some stuff, sleeping
|
2
|
+
[1, 932]: do_somestuff
|
3
|
+
firing :stuff_happens
|
4
|
+
[1] stuff_happened callback: 824
|
5
|
+
firing :other_stuff_happens
|
6
|
+
[n/a] same_stuff_happened callback: n/a
|
7
|
+
[1, 932]: do_somestuff
|
8
|
+
firing :stuff_happens
|
9
|
+
[1] stuff_happened callback: 407
|
10
|
+
[1, 932]: do_somestuff
|
11
|
+
firing :stuff_happens
|
12
|
+
[1] stuff_happened callback: 841
|
13
|
+
firing :other_stuff_happens
|
14
|
+
[n/a] same_stuff_happened callback: n/a
|
15
|
+
[1, 932]: do_somestuff
|
16
|
+
firing :stuff_happens
|
17
|
+
[1] stuff_happened callback: 779
|
18
|
+
[1] slept
|
19
|
+
[2] did some stuff, sleeping
|
20
|
+
firing :other_stuff_happens
|
21
|
+
[n/a] same_stuff_happened callback: n/a
|
22
|
+
[1, 932]: do_somestuff
|
23
|
+
firing :stuff_happens
|
24
|
+
[1] stuff_happened callback: 252
|
25
|
+
[2, 316]: do_somestuff
|
26
|
+
firing :stuff_happens
|
27
|
+
[2] stuff_happened callback: 174
|
28
|
+
firing :other_stuff_happens
|
29
|
+
[n/a] same_stuff_happened callback: n/a
|
30
|
+
[2, 316]: do_somestuff
|
31
|
+
firing :stuff_happens
|
32
|
+
[2] stuff_happened callback: 193
|
33
|
+
[1, 932]: do_somestuff
|
34
|
+
firing :stuff_happens
|
35
|
+
[1] stuff_happened callback: 535
|
36
|
+
[2] slept
|
37
|
+
[3] did some stuff, sleeping
|
38
|
+
firing :other_stuff_happens
|
39
|
+
[n/a] same_stuff_happened callback: n/a
|
40
|
+
[2, 316]: do_somestuff
|
41
|
+
firing :stuff_happens
|
42
|
+
[2] stuff_happened callback: 420
|
43
|
+
[3, 748]: do_somestuff
|
44
|
+
firing :stuff_happens
|
45
|
+
[3] stuff_happened callback: 545
|
46
|
+
[2, 316]: do_somestuff
|
47
|
+
firing :stuff_happens
|
48
|
+
[2] stuff_happened callback: 471
|
49
|
+
[3, 748]: do_somestuff
|
50
|
+
firing :stuff_happens
|
51
|
+
[2, 316]: do_somestuff
|
52
|
+
[3] stuff_happened callback: 266
|
53
|
+
firing :stuff_happens
|
54
|
+
[2] stuff_happened callback: 481
|
55
|
+
[3] slept
|
56
|
+
all done
|
data/lib/.DS_Store
ADDED
Binary file
|
data/lib/eventable/eventable.rb
CHANGED
@@ -3,40 +3,40 @@ require 'thread'
|
|
3
3
|
# Incredibly simple framework for adding events
|
4
4
|
module Eventable
|
5
5
|
|
6
|
-
|
7
|
-
attr_reader :callbacks
|
6
|
+
module EventableEventMethods
|
8
7
|
|
9
|
-
# Add the #event method to the extending class not instances of that class
|
10
|
-
def self.included(base)
|
11
|
-
base.extend(EventableClassMethods)
|
12
|
-
end
|
13
|
-
|
14
|
-
module EventableClassMethods
|
15
|
-
|
16
8
|
# register an event
|
17
9
|
def event(event_name)
|
18
10
|
@eventable_events ||= []
|
19
11
|
@eventable_events << event_name unless @eventable_events.include? event_name
|
20
12
|
end
|
21
|
-
|
13
|
+
|
22
14
|
# returns a list of registered events
|
23
15
|
def events
|
24
16
|
@eventable_events.clone
|
25
17
|
end
|
26
|
-
|
18
|
+
|
27
19
|
end
|
28
20
|
|
29
21
|
def events
|
30
22
|
self.class.events
|
31
23
|
end
|
32
|
-
|
24
|
+
|
25
|
+
# Allows for dynamic discovery of hooked callbacks
|
26
|
+
attr_reader :callbacks
|
27
|
+
|
28
|
+
# Add the #event method to the extending class not instances of that class
|
29
|
+
def self.included(base)
|
30
|
+
base.extend(EventableEventMethods)
|
31
|
+
end
|
32
|
+
|
33
33
|
def initialize
|
34
|
+
super
|
34
35
|
@eventable_mutex = Mutex.new
|
35
36
|
end
|
36
|
-
|
37
|
+
|
37
38
|
# When the event happens the class where it happens runs this
|
38
39
|
def fire_event(event, *return_value, &block)
|
39
|
-
# We don't want the callback array being altered when we're trying to read it
|
40
40
|
check_mutex
|
41
41
|
@eventable_mutex.synchronize {
|
42
42
|
|
@@ -45,7 +45,9 @@ module Eventable
|
|
45
45
|
@callbacks[event].each do |listener_id, callbacks|
|
46
46
|
begin
|
47
47
|
listener = ObjectSpace._id2ref(listener_id)
|
48
|
-
callbacks.each
|
48
|
+
callbacks.each do |callback|
|
49
|
+
Thread.new {listener.send callback, *return_value, &block}
|
50
|
+
end
|
49
51
|
rescue RangeError => re
|
50
52
|
# Don't bubble up a missing recycled object, I don't care if it's not there, I just won't call it
|
51
53
|
raise re unless re.message.match(/is recycled object/)
|
@@ -61,19 +63,19 @@ module Eventable
|
|
61
63
|
raise ArgumentError, "Missing parameter :#{parameter}" unless args[parameter]
|
62
64
|
end
|
63
65
|
|
64
|
-
|
65
|
-
raise Errors::UnknownEvent unless events.include? event
|
66
|
-
|
67
|
-
# Make access to the callback cache threadsafe
|
66
|
+
# Make access to the callback array threadsafe
|
68
67
|
check_mutex
|
69
68
|
@eventable_mutex.synchronize {
|
69
|
+
event = args[:event]
|
70
|
+
raise Errors::UnknownEvent unless events.include? event
|
71
|
+
|
70
72
|
@callbacks ||= {}
|
71
73
|
@callbacks[event] ||= {}
|
72
|
-
|
74
|
+
|
73
75
|
listener = args[:listener]
|
74
76
|
listener_id = listener.object_id
|
75
77
|
callback = args[:callback]
|
76
|
-
|
78
|
+
|
77
79
|
# save the callback info without creating a reference to the object
|
78
80
|
@callbacks[event][listener_id] ||= []
|
79
81
|
@callbacks[event][listener_id] << callback
|
@@ -92,7 +94,7 @@ module Eventable
|
|
92
94
|
@eventable_mutex.synchronize {
|
93
95
|
event = args[:event]
|
94
96
|
return unless @callbacks && @callbacks[event]
|
95
|
-
|
97
|
+
|
96
98
|
listener_id = args[:listener_id] || args[:listener].object_id
|
97
99
|
callback = args[:callback]
|
98
100
|
@callbacks[event].delete_if do |listener, callbacks|
|
@@ -103,7 +105,7 @@ module Eventable
|
|
103
105
|
end
|
104
106
|
|
105
107
|
private
|
106
|
-
|
108
|
+
|
107
109
|
def check_mutex
|
108
110
|
raise Errors::SuperNotCalledInInitialize, "You must include super in your class's initialize method" unless @eventable_mutex
|
109
111
|
end
|
@@ -113,7 +115,5 @@ module Eventable
|
|
113
115
|
def unregister_finalizer(event, listener_id, callback)
|
114
116
|
proc {unregister_for_event(event: event, listener_id: listener_id, callback: callback)}
|
115
117
|
end
|
116
|
-
|
117
|
-
end
|
118
|
-
|
119
118
|
|
119
|
+
end
|
data/lib/eventable/version.rb
CHANGED
data/spec/.DS_Store
ADDED
Binary file
|
@@ -1,5 +1,8 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
|
+
# Callbacks are threaded to avoid blocking so tests need to wait for the callback to be scheduled and run
|
4
|
+
CALLBACK_WAIT = 0.01
|
5
|
+
|
3
6
|
describe Eventable do
|
4
7
|
|
5
8
|
before(:each) do
|
@@ -15,8 +18,8 @@ describe Eventable do
|
|
15
18
|
include Eventable
|
16
19
|
event :do_stuff
|
17
20
|
end
|
18
|
-
|
19
|
-
|
21
|
+
f = Foo.new
|
22
|
+
f.fire_event(:do_stuff)
|
20
23
|
}.should_not raise_error
|
21
24
|
end
|
22
25
|
|
@@ -33,7 +36,7 @@ describe Eventable do
|
|
33
36
|
f.fire_event(:do_stuff)
|
34
37
|
}.should_not raise_error
|
35
38
|
end
|
36
|
-
|
39
|
+
|
37
40
|
it "should raise an error if super is not called in initialize" do
|
38
41
|
lambda{
|
39
42
|
class Foo
|
@@ -46,7 +49,7 @@ describe Eventable do
|
|
46
49
|
f.fire_event(:do_stuff)
|
47
50
|
}.should raise_error(Eventable::Errors::SuperNotCalledInInitialize)
|
48
51
|
end
|
49
|
-
|
52
|
+
|
50
53
|
end
|
51
54
|
|
52
55
|
context "when specifiying an event" do
|
@@ -54,7 +57,7 @@ describe Eventable do
|
|
54
57
|
it 'should list the event from the class' do
|
55
58
|
EventClass.events.should include(:stuff_happens)
|
56
59
|
end
|
57
|
-
|
60
|
+
|
58
61
|
it 'should list more than one event' do
|
59
62
|
EventClass.events.should include(:other_stuff_happens)
|
60
63
|
end
|
@@ -62,42 +65,39 @@ describe Eventable do
|
|
62
65
|
it 'should list the event from an instance of the class' do
|
63
66
|
@evented.events.should include(:stuff_happens)
|
64
67
|
end
|
65
|
-
|
68
|
+
|
66
69
|
it 'should list more than one event from an instance' do
|
67
70
|
@evented.events.should include(:other_stuff_happens)
|
68
71
|
end
|
69
72
|
|
70
73
|
it "should not add an event that's already been added" do
|
71
74
|
eval %{
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
75
|
+
class EventClass
|
76
|
+
include Eventable
|
77
|
+
event :stuff_happens
|
78
|
+
end
|
76
79
|
}
|
77
80
|
EventClass.events.count.should == 2
|
78
81
|
end
|
79
82
|
|
80
83
|
it "should not add events to other classes" do
|
81
84
|
eval %{
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
85
|
+
class EventClass2
|
86
|
+
include Eventable
|
87
|
+
event :some_other_event
|
88
|
+
end
|
86
89
|
}
|
87
90
|
EventClass.events.should_not include(:some_other_event)
|
88
91
|
end
|
89
|
-
|
92
|
+
|
90
93
|
it "should not allow its event list to be altered external" do
|
91
94
|
events = EventClass.events
|
92
95
|
events.pop
|
93
96
|
events.should_not == EventClass.events
|
94
97
|
end
|
95
|
-
|
96
|
-
it "should allow multiple classes to use the mixin" do
|
97
|
-
end
|
98
|
-
|
98
|
+
|
99
99
|
end
|
100
|
-
|
100
|
+
|
101
101
|
context "when registering for an event" do
|
102
102
|
|
103
103
|
context "and there is a missing parameter" do
|
@@ -141,7 +141,7 @@ describe Eventable do
|
|
141
141
|
@evented.register_for_event(event: :other_stuff_happens, listener: @listener, callback: :callback)
|
142
142
|
@evented.callbacks.count.should == 2
|
143
143
|
end
|
144
|
-
|
144
|
+
|
145
145
|
it "should not add a callback that's already been added" do
|
146
146
|
@evented.register_for_event(event: :stuff_happens, listener: @listener, callback: :callback)
|
147
147
|
@evented.register_for_event(event: :stuff_happens, listener: @listener, callback: :callback)
|
@@ -159,6 +159,7 @@ describe Eventable do
|
|
159
159
|
@evented.register_for_event(event: :stuff_happens, listener: @listener, callback: :callback)
|
160
160
|
@evented.register_for_event(event: :stuff_happens, listener: @listener, callback: :callback2)
|
161
161
|
@evented.do_event
|
162
|
+
sleep(CALLBACK_WAIT)
|
162
163
|
@listener.callback?.should be_true
|
163
164
|
@listener.callback2?.should be_true
|
164
165
|
end
|
@@ -167,6 +168,7 @@ describe Eventable do
|
|
167
168
|
# should be a no brainer because a class is an object too, but just to be sure
|
168
169
|
@evented.register_for_event(event: :stuff_happens, listener: ListenClass, callback: :class_callback)
|
169
170
|
@evented.do_event
|
171
|
+
sleep(CALLBACK_WAIT)
|
170
172
|
ListenClass.class_callback?.should be_true
|
171
173
|
end
|
172
174
|
|
@@ -180,6 +182,7 @@ describe Eventable do
|
|
180
182
|
@evented.register_for_event(event: :stuff_happens, listener: @listener, callback: :callback)
|
181
183
|
another_evented.register_for_event(event: :stuff_happens, listener: another_listener, callback: :callback)
|
182
184
|
@evented.do_event
|
185
|
+
sleep(CALLBACK_WAIT)
|
183
186
|
@listener.callback?.should be_true
|
184
187
|
another_listener.callback?.should_not be_true
|
185
188
|
end
|
@@ -191,6 +194,7 @@ describe Eventable do
|
|
191
194
|
another_evented.register_for_event(event: :stuff_happens, listener: another_listener, callback: :callback2)
|
192
195
|
@evented.do_event
|
193
196
|
another_evented.do_event
|
197
|
+
sleep(CALLBACK_WAIT)
|
194
198
|
@listener.callback?.should be_true
|
195
199
|
another_listener.callback2?.should be_true
|
196
200
|
end
|
@@ -198,28 +202,28 @@ describe Eventable do
|
|
198
202
|
end
|
199
203
|
|
200
204
|
end
|
201
|
-
|
205
|
+
|
202
206
|
context "when unregistering for an event" do
|
203
207
|
|
204
208
|
it "should not throw an error if unregistering for an event you weren't registered for" do
|
205
209
|
# Is this supporting sloppy programming(bad) or lazy programming(good)?
|
206
210
|
lambda{@evented.unregister_for_event(event: :stuff_happens, listener: @listener, callback: :callback)}.should_not raise_error
|
207
211
|
end
|
208
|
-
|
212
|
+
|
209
213
|
it "should remove a callback" do
|
210
214
|
@evented.register_for_event(event: :stuff_happens, listener: @listener, callback: :callback)
|
211
215
|
@evented.callbacks[:stuff_happens].keys.should include(@listener.object_id) # <= just to be sure...
|
212
216
|
@evented.unregister_for_event(event: :stuff_happens, listener: @listener, callback: :callback)
|
213
217
|
@evented.callbacks[:stuff_happens].keys.should_not include(@listener.object_id)
|
214
218
|
end
|
215
|
-
|
219
|
+
|
216
220
|
it "should not call a callback that has been removed" do
|
217
221
|
@evented.register_for_event(event: :stuff_happens, listener: @listener, callback: :callback)
|
218
222
|
@evented.unregister_for_event(event: :stuff_happens, listener: @listener, callback: :callback)
|
219
223
|
@evented.do_event
|
220
224
|
@listener.callback?.should_not be_true
|
221
225
|
end
|
222
|
-
|
226
|
+
|
223
227
|
it "should automatically remove callbacks to objects that are garbage collected" do
|
224
228
|
listener_object_id = nil
|
225
229
|
(0..1).each do
|
@@ -230,7 +234,7 @@ describe Eventable do
|
|
230
234
|
GC.start
|
231
235
|
@evented.callbacks[:stuff_happens].keys.should_not include(listener_object_id)
|
232
236
|
end
|
233
|
-
|
237
|
+
|
234
238
|
end
|
235
239
|
|
236
240
|
context "when an event is fired" do
|
@@ -249,39 +253,40 @@ describe Eventable do
|
|
249
253
|
@evented.do_event
|
250
254
|
lambda{@evented.do_event}.should_not raise_error
|
251
255
|
end
|
252
|
-
|
256
|
+
|
253
257
|
it "should call back the specified method when the event is fired" do
|
254
258
|
@evented.register_for_event(event: :stuff_happens, listener: @listener, callback: :callback)
|
255
259
|
@evented.do_event
|
260
|
+
sleep(CALLBACK_WAIT)
|
256
261
|
@listener.callback?.should be_true
|
257
262
|
end
|
258
|
-
|
263
|
+
|
259
264
|
it "should not call back the wrong method when the event is fired" do
|
260
265
|
@evented.register_for_event(event: :stuff_happens, listener: @listener, callback: :callback)
|
261
266
|
@evented.do_event
|
262
267
|
@listener.callback2?.should_not be_true
|
263
268
|
end
|
264
|
-
|
269
|
+
|
265
270
|
it "should call back more than one class" do
|
266
271
|
listener2 = ListenClass.new
|
267
|
-
|
272
|
+
|
268
273
|
@evented.register_for_event(event: :stuff_happens, listener: @listener, callback: :callback)
|
269
274
|
@evented.register_for_event(event: :stuff_happens, listener: listener2, callback: :callback2)
|
270
|
-
|
275
|
+
|
271
276
|
@evented.do_event
|
272
|
-
|
277
|
+
sleep(CALLBACK_WAIT)
|
273
278
|
@listener.callback?.should be_true
|
274
279
|
listener2.callback2?.should be_true
|
275
280
|
end
|
276
281
|
|
277
282
|
it "should not call back the wrong method when using multiple classes" do
|
278
283
|
listener2 = ListenClass.new
|
279
|
-
|
284
|
+
|
280
285
|
@evented.register_for_event(event: :stuff_happens, listener: @listener, callback: :callback)
|
281
286
|
@evented.register_for_event(event: :stuff_happens, listener: listener2, callback: :callback2)
|
282
|
-
|
287
|
+
|
283
288
|
@evented.do_event
|
284
|
-
|
289
|
+
sleep(CALLBACK_WAIT)
|
285
290
|
@listener.callback2?.should_not be_true
|
286
291
|
listener2.callback?.should_not be_true
|
287
292
|
end
|
@@ -292,6 +297,7 @@ describe Eventable do
|
|
292
297
|
@evented.register_for_event(event: :stuff_happens, listener: @listener, callback: :callback_with_args)
|
293
298
|
a, b, c = rand(100), rand(100), rand(100)
|
294
299
|
@evented.do_event_with_args(a,b,c)
|
300
|
+
sleep(CALLBACK_WAIT)
|
295
301
|
@listener.callback_with_args?.should == [a,b,c]
|
296
302
|
end
|
297
303
|
|
@@ -299,6 +305,7 @@ describe Eventable do
|
|
299
305
|
@evented.register_for_event(event: :stuff_happens, listener: @listener, callback: :callback_with_block)
|
300
306
|
block = proc {"a block"}
|
301
307
|
@evented.do_event_with_block(&block)
|
308
|
+
sleep(CALLBACK_WAIT)
|
302
309
|
@listener.callback_with_block?.should == block
|
303
310
|
end
|
304
311
|
|
@@ -306,17 +313,42 @@ describe Eventable do
|
|
306
313
|
@evented.register_for_event(event: :stuff_happens, listener: @listener, callback: :callback_with_args_and_block)
|
307
314
|
a, b, c, block = rand(100), rand(100), rand(100), proc {"a block"}
|
308
315
|
@evented.do_event_with_args_and_block(a,b,c,&block)
|
316
|
+
sleep(CALLBACK_WAIT)
|
309
317
|
@listener.callback_with_args_and_block?.should == [a,b,c,block]
|
310
318
|
end
|
311
319
|
|
312
320
|
end
|
313
|
-
|
321
|
+
|
322
|
+
context "when multithreading" do
|
323
|
+
|
324
|
+
it "should not block on callbacks" do
|
325
|
+
bc = BlockingClass.new
|
326
|
+
@evented.register_for_event(event: :stuff_happens, listener: bc, callback: :blocking_call)
|
327
|
+
start_time = Time.now
|
328
|
+
@evented.do_event
|
329
|
+
sleep(CALLBACK_WAIT * 2) # Just to make sure the event cycle starts
|
330
|
+
Time.now.should_not > start_time + 1
|
331
|
+
end
|
332
|
+
|
333
|
+
end
|
334
|
+
|
314
335
|
end
|
315
336
|
|
316
337
|
end
|
317
338
|
|
318
339
|
# Test classes
|
319
340
|
|
341
|
+
class BlockingClass
|
342
|
+
def blocking_call
|
343
|
+
# I don't know how long this will take but it's a lot longer than 1 second
|
344
|
+
1000000000.times { Math.sqrt(98979872938749283749729384792734927) }
|
345
|
+
non_blocking_call
|
346
|
+
end
|
347
|
+
def non_blocking_call
|
348
|
+
"all done"
|
349
|
+
end
|
350
|
+
end
|
351
|
+
|
320
352
|
class EventClass
|
321
353
|
include Eventable
|
322
354
|
event :stuff_happens
|
@@ -339,7 +371,7 @@ class AnotherEventClass
|
|
339
371
|
include Eventable
|
340
372
|
event :stuff_happens
|
341
373
|
event :different_happens
|
342
|
-
|
374
|
+
|
343
375
|
def do_event(event=:stuff_happens)
|
344
376
|
fire_event(event)
|
345
377
|
end
|
@@ -391,7 +423,7 @@ class AnotherListenClass
|
|
391
423
|
def callback
|
392
424
|
@callback = true
|
393
425
|
end
|
394
|
-
|
426
|
+
def callback2?
|
395
427
|
@callback2
|
396
428
|
end
|
397
429
|
def callback2
|
data/vendor/.DS_Store
ADDED
Binary file
|
metadata
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
name: eventable
|
3
3
|
version: !ruby/object:Gem::Version
|
4
4
|
prerelease:
|
5
|
-
version: 0.1.
|
5
|
+
version: 0.1.3
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- Mike Bethany
|
@@ -10,7 +10,7 @@ autorequire:
|
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
12
|
|
13
|
-
date: 2011-06-
|
13
|
+
date: 2011-06-29 00:00:00 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: rspec
|
@@ -23,6 +23,17 @@ dependencies:
|
|
23
23
|
version: "2.6"
|
24
24
|
type: :development
|
25
25
|
version_requirements: *id001
|
26
|
+
- !ruby/object:Gem::Dependency
|
27
|
+
name: bundler
|
28
|
+
prerelease: false
|
29
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
30
|
+
none: false
|
31
|
+
requirements:
|
32
|
+
- - ~>
|
33
|
+
- !ruby/object:Gem::Version
|
34
|
+
version: "1.0"
|
35
|
+
type: :development
|
36
|
+
version_requirements: *id002
|
26
37
|
description: Provides an easy to use and understand event model. If you want a simple, light-weight way to add events to your classes this is the solution for you.
|
27
38
|
email:
|
28
39
|
- mikbe.tk@gmail.com
|
@@ -33,6 +44,7 @@ extensions: []
|
|
33
44
|
extra_rdoc_files: []
|
34
45
|
|
35
46
|
files:
|
47
|
+
- .DS_Store
|
36
48
|
- .gitignore
|
37
49
|
- Gemfile
|
38
50
|
- LICENSE.txt
|
@@ -41,16 +53,21 @@ files:
|
|
41
53
|
- autotest/discover.rb
|
42
54
|
- eventable.gemspec
|
43
55
|
- example/example.rb
|
56
|
+
- example/example_output.txt
|
44
57
|
- example/simple_example.rb
|
58
|
+
- example/simple_output.txt
|
59
|
+
- lib/.DS_Store
|
45
60
|
- lib/eventable.rb
|
46
61
|
- lib/eventable/errors.rb
|
47
62
|
- lib/eventable/eventable.rb
|
48
63
|
- lib/eventable/version.rb
|
64
|
+
- spec/.DS_Store
|
49
65
|
- spec/eventable/eventable_spec.rb
|
50
66
|
- spec/spec_helper.rb
|
67
|
+
- vendor/.DS_Store
|
51
68
|
homepage: http://mikbe.tk/projects#eventable
|
52
|
-
licenses:
|
53
|
-
|
69
|
+
licenses:
|
70
|
+
- MIT
|
54
71
|
post_install_message:
|
55
72
|
rdoc_options: []
|
56
73
|
|
@@ -61,7 +78,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
61
78
|
requirements:
|
62
79
|
- - ">="
|
63
80
|
- !ruby/object:Gem::Version
|
64
|
-
version:
|
81
|
+
version: 1.9.2
|
65
82
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
66
83
|
none: false
|
67
84
|
requirements:
|