futuroscope 0.0.4 → 0.0.5

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 3f498b34f03cddab4ebf539fdd57083bb1d91a10
4
- data.tar.gz: 7b0ce96ef70f87813fed0ff2d39384a04be5b01c
3
+ metadata.gz: 3209580d247ece206a07186449942582e6611740
4
+ data.tar.gz: b9b20627ef16e8b590d11d0c5cb1dd636960a76c
5
5
  SHA512:
6
- metadata.gz: 886540396354bfd6f74a730e17a8fb60e9bd59d709bd4b4c8205f13334856a647a6033c42ce9d4eaed003b442c97d9d7e0b457f50f3f2f70f5a9bf5e4dc0e096
7
- data.tar.gz: 2c098214076c334a5979348b5b2ad2b077579c181945f23a81b19f253a7779777182d6027ee1edfec5d8d5adfdcc1ea9f7f6cb564a4e99f1b6b1f970df6ba30b
6
+ metadata.gz: dea9d87bbe54b822f7960a2c412ea1ae3dc94e8c49f2ec8c931d70384aab9fa2ce18a0cb9d3dc2815699f150ef64250865d6b009384e293fe0256841b4d2c661
7
+ data.tar.gz: 209d3d2f712fbf64d4ad07faece782db1c1c998590716e1b55d5d901d5561ff20d764a5a5342fbdf0f35e290c0f790b7f3d60ee892f22e09dd7d6219b16abf43
@@ -1,5 +1,9 @@
1
1
  rvm:
2
+ - 1.8.7
2
3
  - 1.9.3
3
4
  - 2.0.0
5
+ - rbx-18mode
4
6
  - rbx-19mode
7
+ - jruby-18mode
5
8
  - jruby-19mode
9
+ - ree
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/lib/#{m[1]}_spec.rb" }
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 `Rubinius`.
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
- ## Ideas for the future
131
+ ## Thread pool
132
132
 
133
- * Having a thread pool so you can limit maximum concurrency.
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
 
@@ -21,4 +21,5 @@ Gem::Specification.new do |spec|
21
21
  spec.add_development_dependency "bundler", "~> 1.3"
22
22
  spec.add_development_dependency "rake"
23
23
  spec.add_development_dependency "rspec"
24
+ spec.add_development_dependency "rspec-mocks"
24
25
  end
@@ -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
@@ -2,8 +2,8 @@ require 'futuroscope/future'
2
2
  require 'futuroscope/map'
3
3
 
4
4
  module Kernel
5
- def future(&block)
6
- Futuroscope::Future.new(&block)
5
+ def future(pool = Futuroscope.default_pool, &block)
6
+ Futuroscope::Future.new(pool, &block)
7
7
  end
8
8
  end
9
9
 
@@ -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
- @thread = Thread.new do
29
- result = block.call
30
- self.future_value = result
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
- @thread.join
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
@@ -1,3 +1,3 @@
1
1
  module Futuroscope
2
- VERSION = "0.0.4"
2
+ VERSION = "0.0.5"
3
3
  end
@@ -20,7 +20,7 @@ module Futuroscope
20
20
  end
21
21
  end
22
22
 
23
- it "delegates some important methods to the original object's" do
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
@@ -1,4 +1,6 @@
1
- require 'coveralls'
2
- Coveralls.wear!
1
+ if ENV["CI"]
2
+ require 'coveralls'
3
+ Coveralls.wear!
4
+ end
3
5
 
4
6
  require 'futuroscope'
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
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-03 00:00:00.000000000 Z
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