futuroscope 0.0.4 → 0.0.5
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.
- checksums.yaml +4 -4
- data/.travis.yml +4 -0
- data/Guardfile +2 -2
- data/README.md +26 -3
- data/futuroscope.gemspec +1 -0
- data/lib/futuroscope.rb +18 -0
- data/lib/futuroscope/convenience.rb +2 -2
- data/lib/futuroscope/future.rb +11 -6
- data/lib/futuroscope/pool.rb +44 -0
- data/lib/futuroscope/version.rb +1 -1
- data/spec/futuroscope/future_spec.rb +7 -1
- data/spec/futuroscope/pool_spec.rb +25 -0
- data/spec/futuroscope_spec.rb +18 -0
- data/spec/spec_helper.rb +4 -2
- metadata +21 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 3209580d247ece206a07186449942582e6611740
|
|
4
|
+
data.tar.gz: b9b20627ef16e8b590d11d0c5cb1dd636960a76c
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: dea9d87bbe54b822f7960a2c412ea1ae3dc94e8c49f2ec8c931d70384aab9fa2ce18a0cb9d3dc2815699f150ef64250865d6b009384e293fe0256841b4d2c661
|
|
7
|
+
data.tar.gz: 209d3d2f712fbf64d4ad07faece782db1c1c998590716e1b55d5d901d5561ff20d764a5a5342fbdf0f35e290c0f790b7f3d60ee892f22e09dd7d6219b16abf43
|
data/.travis.yml
CHANGED
data/Guardfile
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
# A sample Guardfile
|
|
2
2
|
# More info at https://github.com/guard/guard#readme
|
|
3
3
|
|
|
4
|
-
guard 'rspec' do
|
|
4
|
+
guard 'rspec', bundler: false do
|
|
5
5
|
watch(%r{^spec/.+_spec\.rb$})
|
|
6
|
-
watch(%r{^lib/(.+)\.rb$}) { |m| "spec
|
|
6
|
+
watch(%r{^lib/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
|
|
7
7
|
watch('spec/spec_helper.rb') { "spec" }
|
|
8
8
|
end
|
|
9
9
|
|
data/README.md
CHANGED
|
@@ -23,7 +23,7 @@ method on in it will be forwarded to the block's return value.
|
|
|
23
23
|
If the thread didn't finish yet, it will block the program's execution until
|
|
24
24
|
it's finished. Otherwise, it will immediataly return its value.
|
|
25
25
|
|
|
26
|
-
Futuroscope is tested on `MRI 1.9.3`, `MRI 2.0.0`, `JRuby` and `
|
|
26
|
+
Futuroscope is tested on `MRI 1.9.3`, `MRI 2.0.0`, `MRI 1.8.7`, `JRuby in 1.9 mode`, `JRuby in 1.8 mode`, `Rubinius 1.9 mode`, `Rubinius 1.8 mode` and `REE`.
|
|
27
27
|
|
|
28
28
|
## Installation
|
|
29
29
|
|
|
@@ -128,9 +128,32 @@ If you're looking for other ways to improve your code performance via
|
|
|
128
128
|
concurrency, you should probably deal directly with [Ruby's
|
|
129
129
|
threads](http://ruby-doc.org/core-2.0/Thread.html).
|
|
130
130
|
|
|
131
|
-
##
|
|
131
|
+
## Thread pool
|
|
132
132
|
|
|
133
|
-
|
|
133
|
+
Futures are scheduled in a thread pool that helps managing concurrency in a way
|
|
134
|
+
that doesn't get out of hands. Also comes with great benefits since their
|
|
135
|
+
threads are spawned at load time (and not in runtime).
|
|
136
|
+
|
|
137
|
+
The default thread pool comes with a concurrency of 8 threads, which seems
|
|
138
|
+
reasonable for the most use cases.
|
|
139
|
+
|
|
140
|
+
The default thread pool can be replaced by a new pool with different
|
|
141
|
+
concurrency like this:
|
|
142
|
+
|
|
143
|
+
```Ruby
|
|
144
|
+
Futuroscope.default_pool = Futuroscope::Pool.new(24)
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
Also, each future can be scheduled to a different pool like this:
|
|
148
|
+
|
|
149
|
+
```Ruby
|
|
150
|
+
pool = Futuroscope::Pool.new(32)
|
|
151
|
+
|
|
152
|
+
future = Future.new(pool){ :edballs }
|
|
153
|
+
|
|
154
|
+
# Or with the convenience method
|
|
155
|
+
future = future(pool){ :edballs }
|
|
156
|
+
```
|
|
134
157
|
|
|
135
158
|
## Contributing
|
|
136
159
|
|
data/futuroscope.gemspec
CHANGED
data/lib/futuroscope.rb
CHANGED
|
@@ -1,5 +1,23 @@
|
|
|
1
1
|
require "futuroscope/version"
|
|
2
|
+
require "futuroscope/pool"
|
|
2
3
|
require "futuroscope/future"
|
|
4
|
+
require "futuroscope/map"
|
|
3
5
|
|
|
4
6
|
module Futuroscope
|
|
7
|
+
# Gets the default futuroscope's pool.
|
|
8
|
+
#
|
|
9
|
+
# Returns a Pool
|
|
10
|
+
def self.default_pool
|
|
11
|
+
@default_pool ||= Pool.new
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
# Sets a new default pool. It's useful when you want to set a different
|
|
15
|
+
# number of concurrent threads.
|
|
16
|
+
#
|
|
17
|
+
# Example:
|
|
18
|
+
# Futuroscope.default_pool = Futuroscope::Pool.new(24)
|
|
19
|
+
#
|
|
20
|
+
def self.default_pool=(pool)
|
|
21
|
+
@default_pool = pool
|
|
22
|
+
end
|
|
5
23
|
end
|
data/lib/futuroscope/future.rb
CHANGED
|
@@ -19,16 +19,21 @@ module Futuroscope
|
|
|
19
19
|
# # This will return in 1 second and not 2 if the execution wasn't
|
|
20
20
|
# # deferred to a thread.
|
|
21
21
|
#
|
|
22
|
+
# pool - A pool where all the futures will be scheduled.
|
|
22
23
|
# block - A block that will be run in the background.
|
|
23
24
|
#
|
|
24
25
|
# Returns a Future
|
|
25
|
-
def initialize(&block)
|
|
26
|
+
def initialize(pool = Futuroscope.default_pool, &block)
|
|
26
27
|
@mutex = Mutex.new
|
|
28
|
+
@queue = Queue.new
|
|
29
|
+
@pool = pool
|
|
30
|
+
@block = block
|
|
31
|
+
@pool.queue self
|
|
32
|
+
end
|
|
27
33
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
end
|
|
34
|
+
def run_future
|
|
35
|
+
self.future_value = @block.call
|
|
36
|
+
@queue.push :ok
|
|
32
37
|
end
|
|
33
38
|
|
|
34
39
|
# Semipublic: Returns the future's value. Will wait for the future to be
|
|
@@ -39,7 +44,7 @@ module Futuroscope
|
|
|
39
44
|
@mutex.synchronize do
|
|
40
45
|
return @future_value if defined?(@future_value)
|
|
41
46
|
end
|
|
42
|
-
@
|
|
47
|
+
@queue.pop
|
|
43
48
|
@future_value
|
|
44
49
|
end
|
|
45
50
|
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
require 'thread'
|
|
2
|
+
|
|
3
|
+
module Futuroscope
|
|
4
|
+
# Futuroscope's pool is design to control concurency and keep it between some
|
|
5
|
+
# certain benefits. Moreover, we warm up the threads beforehand so we don't
|
|
6
|
+
# have to spin them up each time a future is created.
|
|
7
|
+
class Pool
|
|
8
|
+
attr_reader :threads
|
|
9
|
+
|
|
10
|
+
# Initializes a new Pool.
|
|
11
|
+
#
|
|
12
|
+
# thread_count - The number of threads that this pool is gonna have
|
|
13
|
+
def initialize(thread_count = 8)
|
|
14
|
+
@thread_count = thread_count
|
|
15
|
+
@mutex = Mutex.new
|
|
16
|
+
@queue = Queue.new
|
|
17
|
+
@threads = Array.new
|
|
18
|
+
spin_threads
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
# Enqueues a new Future into the pool.
|
|
22
|
+
#
|
|
23
|
+
# future - The Future to enqueue.
|
|
24
|
+
def queue(future)
|
|
25
|
+
@queue.push future
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
private
|
|
29
|
+
|
|
30
|
+
def spin_threads
|
|
31
|
+
@thread_count.times do |i|
|
|
32
|
+
@threads << Thread.new do
|
|
33
|
+
loop do
|
|
34
|
+
@queue.pop.run_future
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def finalize
|
|
41
|
+
@threads.each(&:kill)
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
data/lib/futuroscope/version.rb
CHANGED
|
@@ -20,7 +20,7 @@ module Futuroscope
|
|
|
20
20
|
end
|
|
21
21
|
end
|
|
22
22
|
|
|
23
|
-
it "delegates some
|
|
23
|
+
it "delegates some Object methods to the original object's" do
|
|
24
24
|
object = [1, 2, 3]
|
|
25
25
|
future = Future.new{object}
|
|
26
26
|
|
|
@@ -30,5 +30,11 @@ module Futuroscope
|
|
|
30
30
|
expect(future.clone).to eq(object)
|
|
31
31
|
expect(future.to_s).to eq(object.to_s)
|
|
32
32
|
end
|
|
33
|
+
|
|
34
|
+
it "delegates missing methods" do
|
|
35
|
+
object = [1, 2, 3]
|
|
36
|
+
future = Future.new{object}
|
|
37
|
+
expect(future).to_not be_empty
|
|
38
|
+
end
|
|
33
39
|
end
|
|
34
40
|
end
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
require 'futuroscope/pool'
|
|
3
|
+
|
|
4
|
+
module Futuroscope
|
|
5
|
+
describe Pool do
|
|
6
|
+
it "spins up a number of threads" do
|
|
7
|
+
pool = Pool.new(2)
|
|
8
|
+
expect(pool.threads).to have(2).threads
|
|
9
|
+
|
|
10
|
+
pool = Pool.new(3)
|
|
11
|
+
expect(pool.threads).to have(3).threads
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
describe "queue" do
|
|
15
|
+
it "enqueues a job and runs it" do
|
|
16
|
+
pool = Pool.new
|
|
17
|
+
future = double(:future)
|
|
18
|
+
|
|
19
|
+
future.should_receive :run_future
|
|
20
|
+
pool.queue future
|
|
21
|
+
sleep(0.1)
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
require 'futuroscope'
|
|
3
|
+
|
|
4
|
+
describe Futuroscope do
|
|
5
|
+
describe "default_pool" do
|
|
6
|
+
it "returns a pool by default" do
|
|
7
|
+
expect(Futuroscope.default_pool).to be_kind_of(Futuroscope::Pool)
|
|
8
|
+
end
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
describe "default_pool=" do
|
|
12
|
+
it "allows you to set a new default pool" do
|
|
13
|
+
pool = Futuroscope::Pool.new
|
|
14
|
+
Futuroscope.default_pool = pool
|
|
15
|
+
expect(Futuroscope.default_pool).to equal(pool)
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
data/spec/spec_helper.rb
CHANGED
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: futuroscope
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.0.
|
|
4
|
+
version: 0.0.5
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Josep Jaume Rey Peroy
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2013-05-
|
|
11
|
+
date: 2013-05-04 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: bundler
|
|
@@ -52,6 +52,20 @@ dependencies:
|
|
|
52
52
|
- - '>='
|
|
53
53
|
- !ruby/object:Gem::Version
|
|
54
54
|
version: '0'
|
|
55
|
+
- !ruby/object:Gem::Dependency
|
|
56
|
+
name: rspec-mocks
|
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
|
58
|
+
requirements:
|
|
59
|
+
- - '>='
|
|
60
|
+
- !ruby/object:Gem::Version
|
|
61
|
+
version: '0'
|
|
62
|
+
type: :development
|
|
63
|
+
prerelease: false
|
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
65
|
+
requirements:
|
|
66
|
+
- - '>='
|
|
67
|
+
- !ruby/object:Gem::Version
|
|
68
|
+
version: '0'
|
|
55
69
|
description: Futuroscope is yet another simple gem that implements the Futures concurrency
|
|
56
70
|
pattern.
|
|
57
71
|
email:
|
|
@@ -75,10 +89,13 @@ files:
|
|
|
75
89
|
- lib/futuroscope/convenience.rb
|
|
76
90
|
- lib/futuroscope/future.rb
|
|
77
91
|
- lib/futuroscope/map.rb
|
|
92
|
+
- lib/futuroscope/pool.rb
|
|
78
93
|
- lib/futuroscope/version.rb
|
|
79
94
|
- spec/futuroscope/convenience_spec.rb
|
|
80
95
|
- spec/futuroscope/future_spec.rb
|
|
81
96
|
- spec/futuroscope/map_spec.rb
|
|
97
|
+
- spec/futuroscope/pool_spec.rb
|
|
98
|
+
- spec/futuroscope_spec.rb
|
|
82
99
|
- spec/spec_helper.rb
|
|
83
100
|
homepage: ''
|
|
84
101
|
licenses:
|
|
@@ -109,4 +126,6 @@ test_files:
|
|
|
109
126
|
- spec/futuroscope/convenience_spec.rb
|
|
110
127
|
- spec/futuroscope/future_spec.rb
|
|
111
128
|
- spec/futuroscope/map_spec.rb
|
|
129
|
+
- spec/futuroscope/pool_spec.rb
|
|
130
|
+
- spec/futuroscope_spec.rb
|
|
112
131
|
- spec/spec_helper.rb
|