eventable 0.1.0.beta1 → 0.1.0.beta2
Sign up to get free protection for your applications and to get access to all the features.
- data/README.markdown +3 -1
- data/lib/eventable/eventable.rb +37 -22
- data/lib/eventable/version.rb +1 -1
- metadata +4 -4
data/README.markdown
CHANGED
@@ -8,7 +8,9 @@ Provides an easy to use and understand event model. Other systems did way too mu
|
|
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
|
|
11
|
-
You don't have to worry about memory leaks
|
11
|
+
You might be saying, "What about Observable? Why not just use that?" The problem with observable is that it saves a reference to the observing object. If you drop and add a bunch of them you've got the potential for a huge memory leak. With Eventable you don't have to worry about memory leaks because Eventable only make a reference to the listening object when it needs to talk to it and when it's done it disposes of that reference. Eventable will even automatically remove registered listeners when they get garbage collected. You can set up a listener and not worry about removing your event hook yourself, it's done for you.
|
12
|
+
|
13
|
+
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."
|
12
14
|
|
13
15
|
Eventable couldn't be easier to use.
|
14
16
|
|
data/lib/eventable/eventable.rb
CHANGED
@@ -31,10 +31,19 @@ module Eventable
|
|
31
31
|
# When the event happens the class where it happens runs this
|
32
32
|
def fire_event(event, *return_value, &block)
|
33
33
|
return false unless @callbacks[event] && !@callbacks[event].empty?
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
34
|
+
|
35
|
+
# We don't want the callback array being altered when we're trying to read it
|
36
|
+
@mutex.synchronize{
|
37
|
+
@callbacks[event].each do |listener_id, callbacks|
|
38
|
+
begin
|
39
|
+
listener = ObjectSpace._id2ref(listener_id)
|
40
|
+
callbacks.each {|callback| listener.send callback, *return_value, &block}
|
41
|
+
rescue RangeError => re
|
42
|
+
# Don't bubble up a missing recycled object, I don't care if it's not there, I just won't call it
|
43
|
+
raise re unless re.message.match(/is recycled object/)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
}
|
38
47
|
end
|
39
48
|
|
40
49
|
# Allows an object to listen for an event and have a callback run when the event happens
|
@@ -45,23 +54,27 @@ module Eventable
|
|
45
54
|
|
46
55
|
event = args[:event]
|
47
56
|
raise Errors::UnknownEvent unless events.include? event
|
48
|
-
@callbacks ||= {}
|
49
|
-
@callbacks[event] ||= {}
|
50
57
|
|
51
|
-
|
52
|
-
|
53
|
-
|
58
|
+
# Make access to the callback cache threadsafe
|
59
|
+
@mutex ||= Mutex.new
|
60
|
+
@mutex.synchronize {
|
61
|
+
@callbacks ||= {}
|
62
|
+
@callbacks[event] ||= {}
|
54
63
|
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
unregister_finalizer(event, listener_id, callback)
|
63
|
-
)
|
64
|
+
listener = args[:listener]
|
65
|
+
listener_id = listener.object_id
|
66
|
+
callback = args[:callback]
|
67
|
+
|
68
|
+
# save the callback info without creating a reference to the object
|
69
|
+
@callbacks[event][listener_id] ||= []
|
70
|
+
@callbacks[event][listener_id] << callback
|
64
71
|
|
72
|
+
# will remove the object from the callback list if it is destroyed
|
73
|
+
ObjectSpace.define_finalizer(
|
74
|
+
listener,
|
75
|
+
unregister_finalizer(event, listener_id, callback)
|
76
|
+
)
|
77
|
+
}
|
65
78
|
end
|
66
79
|
|
67
80
|
# Allows objects to stop listening to events
|
@@ -72,10 +85,12 @@ module Eventable
|
|
72
85
|
listener_id = args[:listener_id] || args[:listener].object_id
|
73
86
|
callback = args[:callback]
|
74
87
|
|
75
|
-
@
|
76
|
-
callbacks.
|
77
|
-
|
78
|
-
|
88
|
+
@mutex.synchronize {
|
89
|
+
@callbacks[event].delete_if do |listener, callbacks|
|
90
|
+
callbacks.delete(callback) if listener == listener_id
|
91
|
+
callbacks.empty?
|
92
|
+
end
|
93
|
+
}
|
79
94
|
end
|
80
95
|
|
81
96
|
# Wrapper for the finalize proc. You have to call a method
|
data/lib/eventable/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: eventable
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.0.
|
4
|
+
version: 0.1.0.beta2
|
5
5
|
prerelease: 6
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,11 +9,11 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2011-06-
|
12
|
+
date: 2011-06-06 00:00:00.000000000Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rspec
|
16
|
-
requirement: &
|
16
|
+
requirement: &2156717840 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ~>
|
@@ -21,7 +21,7 @@ dependencies:
|
|
21
21
|
version: '2.6'
|
22
22
|
type: :development
|
23
23
|
prerelease: false
|
24
|
-
version_requirements: *
|
24
|
+
version_requirements: *2156717840
|
25
25
|
description: Provides an easy to use and understand event model. If you want a simple
|
26
26
|
way to add events to your classes without a bunch of other unrelated IO stuff this
|
27
27
|
is the solution for you. (If you want to monitor IO events check out EventMachine)
|