await 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.document +5 -0
- data/Gemfile +8 -0
- data/LICENSE.txt +20 -0
- data/README.md +107 -0
- data/Rakefile +35 -0
- data/VERSION +1 -0
- data/await.gemspec +55 -0
- data/lib/await.rb +94 -0
- data/test/helper.rb +31 -0
- data/test/test_await.rb +259 -0
- metadata +105 -0
data/.document
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2012 Scott Tadman, The Working Group Inc.
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,107 @@
|
|
1
|
+
# await
|
2
|
+
|
3
|
+
This implements the await/defer pattern in Ruby using fibers within the
|
4
|
+
EventMachine environment.
|
5
|
+
|
6
|
+
In general terms, `await` is used to define a group of operations that must
|
7
|
+
be completed before processing can continue, and `defer` is used to define
|
8
|
+
these individual operations.
|
9
|
+
|
10
|
+
This can be used to simplify otherwise complicated callback structures where
|
11
|
+
a number of operations can be performed in parallel. Further complexity arises
|
12
|
+
when some of these operations have optional steps.
|
13
|
+
|
14
|
+
## Examples
|
15
|
+
|
16
|
+
In order to execute properly, an `await` call must be created within a fiber
|
17
|
+
that can yield. Since the root fiber cannot yield, a secondary fiber must be
|
18
|
+
created.
|
19
|
+
|
20
|
+
A very simple example shows how a number of timers can be set to simulate
|
21
|
+
some long-running asynchronous operations:
|
22
|
+
|
23
|
+
```ruby
|
24
|
+
require 'await'
|
25
|
+
require 'eventmachine'
|
26
|
+
|
27
|
+
EventMachine.run do
|
28
|
+
Fiber.new do
|
29
|
+
include Await
|
30
|
+
|
31
|
+
now = Time.now
|
32
|
+
await do
|
33
|
+
EventMachine::Timer.new(5, &defer)
|
34
|
+
EventMachine::Timer.new(2, &defer)
|
35
|
+
EventMachine::Timer.new(3, &defer)
|
36
|
+
end
|
37
|
+
|
38
|
+
puts "Took %.1fs to complete" % (Time.now - now).to_f
|
39
|
+
|
40
|
+
EventMachine.stop_event_loop
|
41
|
+
end.resume
|
42
|
+
end
|
43
|
+
```
|
44
|
+
|
45
|
+
In the end you should see that it took only as long as the longest timer.
|
46
|
+
|
47
|
+
In its default state, `defer` is simply used as a trigger. It can also wrap
|
48
|
+
around a callback block to add additional functionality:
|
49
|
+
|
50
|
+
```ruby
|
51
|
+
require 'await'
|
52
|
+
require 'eventmachine'
|
53
|
+
|
54
|
+
EventMachine.run do
|
55
|
+
Fiber.new do
|
56
|
+
include Await
|
57
|
+
|
58
|
+
now = Time.now
|
59
|
+
await do
|
60
|
+
trigger = defer do |x, y|
|
61
|
+
puts "Received arguments: #{[ x, y ].inspect}"
|
62
|
+
end
|
63
|
+
|
64
|
+
EventMachine::Timer.new(4) do
|
65
|
+
trigger.call(1, '2')
|
66
|
+
end
|
67
|
+
|
68
|
+
EventMachine::Timer.new(
|
69
|
+
3,
|
70
|
+
&defer do
|
71
|
+
EventMachine::Timer.new(
|
72
|
+
2,
|
73
|
+
&defer
|
74
|
+
)
|
75
|
+
end
|
76
|
+
)
|
77
|
+
end
|
78
|
+
|
79
|
+
puts "Took %.1fs to complete" % (Time.now - now).to_f
|
80
|
+
|
81
|
+
EventMachine.stop_event_loop
|
82
|
+
end.resume
|
83
|
+
end
|
84
|
+
```
|
85
|
+
|
86
|
+
Since the `defer` method returns a standard Proc callback, it is possible to
|
87
|
+
pass it through as a callback method or to trigger it at an arbitrary time
|
88
|
+
with `call`.
|
89
|
+
|
90
|
+
More examples of callback structures are available in the various unit tests.
|
91
|
+
|
92
|
+
## Troubleshooting
|
93
|
+
|
94
|
+
If the secondary fiber has not been created you will see errors like:
|
95
|
+
|
96
|
+
FiberError: can't yield from root fiber
|
97
|
+
|
98
|
+
Keep in mind that unless a `defer` call is made within a callback then the
|
99
|
+
operation is considered completed. If an additional asynchronous operation
|
100
|
+
must be performed before it is complete, be sure to wrap any and all of these
|
101
|
+
calls with `defer` as well to tag and track them properly.
|
102
|
+
|
103
|
+
## Copyright
|
104
|
+
|
105
|
+
Copyright (c) 2012 Scott Tadman, The Working Group Inc.
|
106
|
+
See LICENSE.txt for further details.
|
107
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
require 'bundler'
|
5
|
+
|
6
|
+
begin
|
7
|
+
Bundler.setup(:default, :development)
|
8
|
+
rescue Bundler::BundlerError => e
|
9
|
+
$stderr.puts e.message
|
10
|
+
$stderr.puts "Run `bundle install` to install missing gems"
|
11
|
+
exit e.status_code
|
12
|
+
end
|
13
|
+
|
14
|
+
require 'rake'
|
15
|
+
require 'jeweler'
|
16
|
+
|
17
|
+
Jeweler::Tasks.new do |gem|
|
18
|
+
gem.name = "await"
|
19
|
+
gem.homepage = "http://github.com/twg/await"
|
20
|
+
gem.license = "MIT"
|
21
|
+
gem.summary = %Q{Asynchronous await/defer methods for organizing callbacks}
|
22
|
+
gem.description = %Q{Implements the await/defer pattern for event-driven or asynchronous Ruby}
|
23
|
+
gem.email = "scott@twg.ca"
|
24
|
+
gem.authors = [ "Scott Tadman" ]
|
25
|
+
end
|
26
|
+
|
27
|
+
Jeweler::RubygemsDotOrgTasks.new
|
28
|
+
|
29
|
+
require 'rake/testtask'
|
30
|
+
|
31
|
+
Rake::TestTask.new(:test) do |test|
|
32
|
+
test.libs << 'lib' << 'test'
|
33
|
+
test.pattern = 'test/**/test_*.rb'
|
34
|
+
test.verbose = true
|
35
|
+
end
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.1.0
|
data/await.gemspec
ADDED
@@ -0,0 +1,55 @@
|
|
1
|
+
# Generated by jeweler
|
2
|
+
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
|
4
|
+
# -*- encoding: utf-8 -*-
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = "await"
|
8
|
+
s.version = "0.1.0"
|
9
|
+
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
+
s.authors = ["Scott Tadman"]
|
12
|
+
s.date = "2012-11-13"
|
13
|
+
s.description = "Implements the await/defer pattern for event-driven or asynchronous Ruby"
|
14
|
+
s.email = "scott@twg.ca"
|
15
|
+
s.extra_rdoc_files = [
|
16
|
+
"LICENSE.txt",
|
17
|
+
"README.md"
|
18
|
+
]
|
19
|
+
s.files = [
|
20
|
+
".document",
|
21
|
+
"Gemfile",
|
22
|
+
"LICENSE.txt",
|
23
|
+
"README.md",
|
24
|
+
"Rakefile",
|
25
|
+
"VERSION",
|
26
|
+
"await.gemspec",
|
27
|
+
"lib/await.rb",
|
28
|
+
"test/helper.rb",
|
29
|
+
"test/test_await.rb"
|
30
|
+
]
|
31
|
+
s.homepage = "http://github.com/twg/await"
|
32
|
+
s.licenses = ["MIT"]
|
33
|
+
s.require_paths = ["lib"]
|
34
|
+
s.rubygems_version = "1.8.24"
|
35
|
+
s.summary = "Asynchronous await/defer methods for organizing callbacks"
|
36
|
+
|
37
|
+
if s.respond_to? :specification_version then
|
38
|
+
s.specification_version = 3
|
39
|
+
|
40
|
+
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
41
|
+
s.add_runtime_dependency(%q<eventmachine>, [">= 0"])
|
42
|
+
s.add_development_dependency(%q<bundler>, [">= 0"])
|
43
|
+
s.add_development_dependency(%q<jeweler>, [">= 0"])
|
44
|
+
else
|
45
|
+
s.add_dependency(%q<eventmachine>, [">= 0"])
|
46
|
+
s.add_dependency(%q<bundler>, [">= 0"])
|
47
|
+
s.add_dependency(%q<jeweler>, [">= 0"])
|
48
|
+
end
|
49
|
+
else
|
50
|
+
s.add_dependency(%q<eventmachine>, [">= 0"])
|
51
|
+
s.add_dependency(%q<bundler>, [">= 0"])
|
52
|
+
s.add_dependency(%q<jeweler>, [">= 0"])
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
data/lib/await.rb
ADDED
@@ -0,0 +1,94 @@
|
|
1
|
+
require 'thread'
|
2
|
+
require 'fiber'
|
3
|
+
|
4
|
+
module Await
|
5
|
+
module ThreadExtension
|
6
|
+
def await
|
7
|
+
# Capture the current context to properly chain this await in
|
8
|
+
parent = @deferred
|
9
|
+
|
10
|
+
deferred = @deferred = {
|
11
|
+
:fiber => Fiber.current
|
12
|
+
}
|
13
|
+
|
14
|
+
if (parent)
|
15
|
+
parent[deferred] = true
|
16
|
+
end
|
17
|
+
|
18
|
+
yield if (block_given?)
|
19
|
+
|
20
|
+
# So long as there is at least one outstanding defer block, this fiber
|
21
|
+
# must continue to yield.
|
22
|
+
while (deferred.size > 1)
|
23
|
+
fiber, trigger, block, args = Fiber.yield
|
24
|
+
|
25
|
+
deferred.delete(trigger)
|
26
|
+
|
27
|
+
if (block)
|
28
|
+
# Always introduce the correct context here by setting the
|
29
|
+
# thread-local @deferred instance variable.
|
30
|
+
@deferred = deferred
|
31
|
+
block.call(*args)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
# If this was part of an existing await call then remove the current
|
36
|
+
# await operation from the list of pending entries.
|
37
|
+
if (parent)
|
38
|
+
if (deferred[:fiber] == Fiber.current)
|
39
|
+
parent.delete(deferred)
|
40
|
+
else
|
41
|
+
parent[:fiber].transfer([ Fiber.current, deferred ])
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
true
|
46
|
+
end
|
47
|
+
|
48
|
+
def defer(&block)
|
49
|
+
deferred = @deferred
|
50
|
+
|
51
|
+
trigger = lambda do |*args|
|
52
|
+
if (deferred[:fiber] == Fiber.current)
|
53
|
+
# Within the same fiber, remove this from the pending list
|
54
|
+
deferred.delete(trigger)
|
55
|
+
|
56
|
+
block.call(*args)
|
57
|
+
else
|
58
|
+
# If this is executing in a different fiber, transfer control back
|
59
|
+
# to the original fiber for reasons of continuity.
|
60
|
+
deferred[:fiber].transfer([ Fiber.current, trigger, block, args ])
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
deferred[trigger] = true
|
65
|
+
|
66
|
+
trigger
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
# Define a group of operations that need to be completed before execution
|
71
|
+
# will continue. The current fiber is suspended until all of the defer
|
72
|
+
# operations have completed.
|
73
|
+
def await(&block)
|
74
|
+
Thread.current.await(&block)
|
75
|
+
end
|
76
|
+
|
77
|
+
# Used to define a deferred operation. The return value is a Proc that can
|
78
|
+
# be passed through as a callback argument to any method. Once the callback
|
79
|
+
# has been executed it is considered complete unless within that callback
|
80
|
+
# other defer or await calls are made.
|
81
|
+
def defer(*args, &block)
|
82
|
+
Thread.current.defer(*args, &block)
|
83
|
+
end
|
84
|
+
|
85
|
+
# Import all mixin methods here as module methods so they can be used
|
86
|
+
# directly without requiring an import.
|
87
|
+
extend self
|
88
|
+
end
|
89
|
+
|
90
|
+
# == Hook Installation ======================================================
|
91
|
+
|
92
|
+
class Thread
|
93
|
+
include Await::ThreadExtension
|
94
|
+
end
|
data/test/helper.rb
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'bundler'
|
3
|
+
|
4
|
+
begin
|
5
|
+
Bundler.setup(:default, :development)
|
6
|
+
rescue Bundler::BundlerError => e
|
7
|
+
$stderr.puts e.message
|
8
|
+
$stderr.puts "Run `bundle install` to install missing gems"
|
9
|
+
exit e.status_code
|
10
|
+
end
|
11
|
+
|
12
|
+
require 'test/unit'
|
13
|
+
|
14
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
15
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
16
|
+
|
17
|
+
require 'await'
|
18
|
+
|
19
|
+
require 'eventmachine'
|
20
|
+
|
21
|
+
class Test::Unit::TestCase
|
22
|
+
def em
|
23
|
+
EventMachine.run do
|
24
|
+
Fiber.new do
|
25
|
+
yield
|
26
|
+
end.resume
|
27
|
+
|
28
|
+
EventMachine.stop_event_loop
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
data/test/test_await.rb
ADDED
@@ -0,0 +1,259 @@
|
|
1
|
+
require File.expand_path('helper', File.dirname(__FILE__))
|
2
|
+
|
3
|
+
class TestAwait < Test::Unit::TestCase
|
4
|
+
include Await
|
5
|
+
|
6
|
+
def test_module
|
7
|
+
assert_equal true, Await.respond_to?(:await)
|
8
|
+
assert_equal true, Await.respond_to?(:defer)
|
9
|
+
end
|
10
|
+
|
11
|
+
def test_await_default_state
|
12
|
+
triggered = false
|
13
|
+
|
14
|
+
em do
|
15
|
+
await do
|
16
|
+
triggered = true
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
assert_equal true, triggered
|
21
|
+
end
|
22
|
+
|
23
|
+
def test_await_block_object
|
24
|
+
trigger = nil
|
25
|
+
exited = false
|
26
|
+
|
27
|
+
em do
|
28
|
+
await do
|
29
|
+
trigger = defer
|
30
|
+
end
|
31
|
+
|
32
|
+
exited = true
|
33
|
+
end
|
34
|
+
|
35
|
+
assert_equal false, exited
|
36
|
+
|
37
|
+
trigger.call
|
38
|
+
|
39
|
+
assert_equal true, exited
|
40
|
+
end
|
41
|
+
|
42
|
+
def test_await_single_defer
|
43
|
+
triggered = false
|
44
|
+
|
45
|
+
em do
|
46
|
+
await do
|
47
|
+
defer do
|
48
|
+
triggered = true
|
49
|
+
end.call
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
assert_equal true, triggered
|
54
|
+
end
|
55
|
+
|
56
|
+
def test_await_nested
|
57
|
+
triggered = 0
|
58
|
+
|
59
|
+
em do
|
60
|
+
await do
|
61
|
+
defer do
|
62
|
+
await do
|
63
|
+
defer do
|
64
|
+
triggered += 1
|
65
|
+
end.call
|
66
|
+
end
|
67
|
+
|
68
|
+
assert_equal 1, triggered
|
69
|
+
|
70
|
+
await do
|
71
|
+
defer do
|
72
|
+
triggered += 2
|
73
|
+
end.call
|
74
|
+
end
|
75
|
+
end.call
|
76
|
+
end
|
77
|
+
|
78
|
+
assert_equal 3, triggered
|
79
|
+
end
|
80
|
+
|
81
|
+
assert_equal 3, triggered
|
82
|
+
end
|
83
|
+
|
84
|
+
def test_await_delayed_defer
|
85
|
+
triggered = false
|
86
|
+
defer_block = nil
|
87
|
+
|
88
|
+
em do
|
89
|
+
await do
|
90
|
+
defer_block = defer do
|
91
|
+
triggered = true
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
assert defer_block
|
97
|
+
assert_equal false, triggered
|
98
|
+
|
99
|
+
assert defer_block
|
100
|
+
defer_block.call
|
101
|
+
|
102
|
+
assert_equal true, triggered
|
103
|
+
end
|
104
|
+
|
105
|
+
def test_await_delayed_double_defer
|
106
|
+
outer_trigger = nil
|
107
|
+
inner_trigger = nil
|
108
|
+
triggered = false
|
109
|
+
continued = false
|
110
|
+
|
111
|
+
em do
|
112
|
+
await do
|
113
|
+
outer_trigger = defer do
|
114
|
+
inner_trigger = defer do
|
115
|
+
triggered = true
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
continued = true
|
121
|
+
end
|
122
|
+
|
123
|
+
assert_equal false, triggered
|
124
|
+
assert_equal false, continued
|
125
|
+
|
126
|
+
assert !inner_trigger
|
127
|
+
|
128
|
+
outer_trigger.call
|
129
|
+
|
130
|
+
assert_equal false, triggered
|
131
|
+
assert_equal false, continued
|
132
|
+
|
133
|
+
assert inner_trigger
|
134
|
+
|
135
|
+
inner_trigger.call
|
136
|
+
|
137
|
+
assert_equal true, triggered
|
138
|
+
assert_equal true, continued
|
139
|
+
end
|
140
|
+
|
141
|
+
def test_await_nested_delayed_trigger
|
142
|
+
outer_trigger = nil
|
143
|
+
inner_trigger = nil
|
144
|
+
triggered = false
|
145
|
+
continued = false
|
146
|
+
|
147
|
+
em do
|
148
|
+
await do
|
149
|
+
outer_trigger = defer do
|
150
|
+
await do
|
151
|
+
inner_trigger = defer do
|
152
|
+
triggered = true
|
153
|
+
end
|
154
|
+
end
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
continued = true
|
159
|
+
end
|
160
|
+
|
161
|
+
assert_equal false, triggered
|
162
|
+
assert_equal false, continued
|
163
|
+
|
164
|
+
assert !inner_trigger
|
165
|
+
|
166
|
+
outer_trigger.call
|
167
|
+
|
168
|
+
assert_equal false, triggered
|
169
|
+
assert_equal false, continued
|
170
|
+
|
171
|
+
assert inner_trigger
|
172
|
+
|
173
|
+
inner_trigger.call
|
174
|
+
|
175
|
+
assert_equal true, triggered
|
176
|
+
assert_equal true, continued
|
177
|
+
end
|
178
|
+
|
179
|
+
def test_await_delayed_defer_callback
|
180
|
+
triggered = false
|
181
|
+
trigger_callback = nil
|
182
|
+
results = nil
|
183
|
+
|
184
|
+
em do
|
185
|
+
await do
|
186
|
+
trigger_callback = defer do |*args|
|
187
|
+
results = args
|
188
|
+
end
|
189
|
+
end
|
190
|
+
|
191
|
+
triggered = true
|
192
|
+
end
|
193
|
+
|
194
|
+
assert_equal false, triggered
|
195
|
+
|
196
|
+
assert trigger_callback
|
197
|
+
trigger_callback.call(1, :two, '3')
|
198
|
+
|
199
|
+
assert_equal true, triggered
|
200
|
+
assert_equal [ 1, :two, '3' ], results
|
201
|
+
end
|
202
|
+
|
203
|
+
def test_await_multiple_defer
|
204
|
+
triggered = false
|
205
|
+
triggers = [ ]
|
206
|
+
count = 10
|
207
|
+
|
208
|
+
em do
|
209
|
+
await do
|
210
|
+
count.times do
|
211
|
+
triggers << defer
|
212
|
+
end
|
213
|
+
end
|
214
|
+
|
215
|
+
triggered = true
|
216
|
+
end
|
217
|
+
|
218
|
+
assert_equal false, triggered
|
219
|
+
|
220
|
+
while (triggers.length > 1)
|
221
|
+
triggers.pop.call
|
222
|
+
end
|
223
|
+
|
224
|
+
assert_equal false, triggered
|
225
|
+
|
226
|
+
triggers.pop.call
|
227
|
+
|
228
|
+
assert_equal true, triggered
|
229
|
+
end
|
230
|
+
|
231
|
+
def test_await_chained_defer
|
232
|
+
triggered = false
|
233
|
+
trigger_block_outer = nil
|
234
|
+
trigger_block_inner = nil
|
235
|
+
|
236
|
+
em do
|
237
|
+
await do
|
238
|
+
trigger_block_outer = defer do
|
239
|
+
trigger_block_inner = defer do
|
240
|
+
end
|
241
|
+
end
|
242
|
+
end
|
243
|
+
|
244
|
+
triggered = true
|
245
|
+
end
|
246
|
+
|
247
|
+
assert_equal false, triggered
|
248
|
+
|
249
|
+
assert trigger_block_outer
|
250
|
+
trigger_block_outer.call
|
251
|
+
|
252
|
+
assert_equal false, triggered
|
253
|
+
|
254
|
+
assert trigger_block_inner
|
255
|
+
trigger_block_inner.call
|
256
|
+
|
257
|
+
assert_equal true, triggered
|
258
|
+
end
|
259
|
+
end
|
metadata
ADDED
@@ -0,0 +1,105 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: await
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Scott Tadman
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-11-13 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: eventmachine
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '0'
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: bundler
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ! '>='
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '0'
|
38
|
+
type: :development
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0'
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: jeweler
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ! '>='
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '0'
|
54
|
+
type: :development
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ! '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
description: Implements the await/defer pattern for event-driven or asynchronous Ruby
|
63
|
+
email: scott@twg.ca
|
64
|
+
executables: []
|
65
|
+
extensions: []
|
66
|
+
extra_rdoc_files:
|
67
|
+
- LICENSE.txt
|
68
|
+
- README.md
|
69
|
+
files:
|
70
|
+
- .document
|
71
|
+
- Gemfile
|
72
|
+
- LICENSE.txt
|
73
|
+
- README.md
|
74
|
+
- Rakefile
|
75
|
+
- VERSION
|
76
|
+
- await.gemspec
|
77
|
+
- lib/await.rb
|
78
|
+
- test/helper.rb
|
79
|
+
- test/test_await.rb
|
80
|
+
homepage: http://github.com/twg/await
|
81
|
+
licenses:
|
82
|
+
- MIT
|
83
|
+
post_install_message:
|
84
|
+
rdoc_options: []
|
85
|
+
require_paths:
|
86
|
+
- lib
|
87
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
88
|
+
none: false
|
89
|
+
requirements:
|
90
|
+
- - ! '>='
|
91
|
+
- !ruby/object:Gem::Version
|
92
|
+
version: '0'
|
93
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
94
|
+
none: false
|
95
|
+
requirements:
|
96
|
+
- - ! '>='
|
97
|
+
- !ruby/object:Gem::Version
|
98
|
+
version: '0'
|
99
|
+
requirements: []
|
100
|
+
rubyforge_project:
|
101
|
+
rubygems_version: 1.8.24
|
102
|
+
signing_key:
|
103
|
+
specification_version: 3
|
104
|
+
summary: Asynchronous await/defer methods for organizing callbacks
|
105
|
+
test_files: []
|