async_emitter 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (3) hide show
  1. checksums.yaml +15 -0
  2. data/lib/async_emitter.rb +132 -0
  3. metadata +44 -0
checksums.yaml ADDED
@@ -0,0 +1,15 @@
1
+ ---
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ OGI1OGE0ZDUzZTIwN2JiMmFmMWY5N2VhNDVlYWRjM2NjOTIwNGVjOQ==
5
+ data.tar.gz: !binary |-
6
+ NzFlMzk0NzAxNjJiZWQxNWI1ZDI3Y2MxNDRjMDQ1MDUzNDA4YzNjZQ==
7
+ SHA512:
8
+ metadata.gz: !binary |-
9
+ ZTRmNTJkOTBjMTRmYmJlYjIyZmRkM2Y4NzBmYjRiMmE0OWMwMmMzZWQ2NTRj
10
+ YjI0OGMwM2MyODgyOTA5NGIyNjU5Yjk5MTY3OTllNTJiZjI4NWVhZTA5NDlm
11
+ MmI2ZjMzMTY1MmVjNTRhYmU5NzJkMzlkMWNlOGU1NmQ1YzA1OGI=
12
+ data.tar.gz: !binary |-
13
+ OGVjMTJmYjc0MjYxZDdhMzMzYjU3NzkxMjU3OTQ2YmUyMTU2YjkyYmVmZTgw
14
+ MDcyMmNkZTUwNjdhNTIyMGM0ZmM1MDk3YzQ2ZmViMjQwYjAzOGNjMDU1MjY1
15
+ N2YwZjkxM2EzMzJkMWUwOWI4OTAwY2M5MzkxMjllYWU0Y2Q2YTc=
@@ -0,0 +1,132 @@
1
+ require 'thread'
2
+
3
+ class AsyncEmitter
4
+ =begin
5
+ The AsyncEmitter class provides a mechanism for asyncronous communication
6
+ in Ruby programs. Each instantiation provides notification of events
7
+ registered using any object that is valid as a Hash key. Multiple
8
+ events can be registered for each key and listeners can be registered
9
+ for one or many events. Listeners for a key event can be released.
10
+
11
+ example:
12
+ emitter = AsyncEmitter.new
13
+ emitter.on :error, lambda { |e| puts "Error: #{e}" }
14
+ emitter.on :data, lambda { |data| puts "Data: #{data}" }
15
+
16
+ begin
17
+ data = get_data_from_somewhere
18
+ emitter.emit :data, data
19
+ rescue Exception => e
20
+ emitter.emit :error, e
21
+ end
22
+
23
+ Where more then one listener is registered for an event they are
24
+ notified in the order they are recieved.
25
+ =end
26
+
27
+ def initialize
28
+ @emissions = {}
29
+ end
30
+
31
+
32
+ ########################################################################
33
+ # Register for notification
34
+ #
35
+ # token - any valid Hash key representing the event
36
+ # p - a procedure to be called on notification
37
+ # once_only - if true the notification is removed after being fired once
38
+ # ######################################################################
39
+ def on (token, p, once_only=false)
40
+ @emissions[token] ||= {}
41
+ @emissions[token][:p] ||= []
42
+ @emissions[token][:data] ||= []
43
+ @emissions[token][:semaphore] ||= Mutex.new
44
+ @emissions[token][:cv] ||= ConditionVariable.new
45
+
46
+ @emissions[token][:p].push Hash[:p => p, :o => once_only]
47
+
48
+ @emissions[token][:thread] ||= Thread.new do
49
+
50
+ @emissions[token][:active] = true
51
+
52
+ while @emissions[token][:active]
53
+ @emissions[token][:semaphore].synchronize do
54
+ self.post_data_for token
55
+ @emissions[token][:cv].wait @emissions[token][:semaphore]
56
+ if @emissions[token][:active]
57
+ self.post_data_for token
58
+ end
59
+ end
60
+ end
61
+
62
+ end
63
+
64
+ end
65
+
66
+ ########################################################################
67
+ # Register for single notification - convenience and self documenting
68
+ # method for: on token, proc, true
69
+ #
70
+ # token - any valid Hash key representing the event
71
+ # p - a procedure to be called on notification
72
+ # ######################################################################
73
+ def once (token, p)
74
+ self.on token, p, true
75
+ end
76
+
77
+ def emit (token, data)
78
+ @emissions[token][:semaphore] ||= Mutex.new
79
+ @emissions[token][:cv] ||= ConditionVariable.new
80
+ @emissions[token][:data] ||= []
81
+
82
+ @emissions[token][:semaphore].synchronize do
83
+ @emissions[token][:data].push data
84
+ @emissions[token][:cv].signal
85
+ end
86
+
87
+ end
88
+
89
+
90
+ ########################################################################
91
+ # Remove notification for an event
92
+ #
93
+ # token - Hash key representing the event
94
+ ########################################################################
95
+ def release (token)
96
+ @emissions[token][:active] = false
97
+ Thread.kill @emissions[token][:thread]
98
+ end
99
+
100
+ protected
101
+ def post_data_for (token)
102
+ @emissions[token][:p].each_index do |i|
103
+ o = @emissions[token][:p][i][:o]
104
+ p = @emissions[token][:p][i][:p]
105
+
106
+ if o
107
+ @emissions[token][:p].slice! i
108
+ end
109
+
110
+ if i >= @emissions[token][:p].length - 1
111
+ while @emissions[token][:data].length > 0 do
112
+ data = @emissions[token][:data].shift
113
+ p.call data
114
+ if o
115
+ @emissions[token][:data] = []
116
+ break
117
+ end
118
+ end
119
+ else
120
+ @emissions[token][:data].each do |data|
121
+ p.call data
122
+ if o
123
+ break
124
+ end
125
+ end
126
+ end
127
+
128
+ end
129
+ end
130
+ end
131
+
132
+
metadata ADDED
@@ -0,0 +1,44 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: async_emitter
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Greg Martin
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-04-25 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: An asyncronous emitter class for ruby
14
+ email: greg@softsprocket.com
15
+ executables: []
16
+ extensions: []
17
+ extra_rdoc_files: []
18
+ files:
19
+ - lib/async_emitter.rb
20
+ homepage: http://rubygems.org/gems/async_emitter.rb
21
+ licenses:
22
+ - MIT
23
+ metadata: {}
24
+ post_install_message:
25
+ rdoc_options: []
26
+ require_paths:
27
+ - lib
28
+ required_ruby_version: !ruby/object:Gem::Requirement
29
+ requirements:
30
+ - - ! '>='
31
+ - !ruby/object:Gem::Version
32
+ version: '0'
33
+ required_rubygems_version: !ruby/object:Gem::Requirement
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ requirements: []
39
+ rubyforge_project:
40
+ rubygems_version: 2.4.6
41
+ signing_key:
42
+ specification_version: 4
43
+ summary: AsyncEmitter
44
+ test_files: []