await 0.1.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/.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: []
|