Skip to content

Commit 4135a39

Browse files
committed
Merge branch 'master' into tvars.
2 parents d239b74 + 2d40427 commit 4135a39

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

60 files changed

+2512
-1019
lines changed

Gemfile

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,14 @@ gemspec
55
group :development do
66
gem 'rake', '~> 10.1.1'
77
gem 'countloc', '~> 0.4.0', platforms: :mri
8+
gem 'yard', '~> 0.8.7.3'
9+
gem 'inch', '~> 0.3.2', platforms: :mri
810
end
911

1012
group :testing do
1113
gem 'rspec', '~> 2.14.1'
1214
gem 'simplecov', '~> 0.8.2'
1315
gem 'coveralls', '~> 0.7.0', require: false
14-
gem 'yard', '~> 0.8.7.3'
1516
gem 'faker', '~> 1.3.0'
1617
gem 'timecop', '~> 0.7.1'
1718
end

README.md

Lines changed: 82 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,39 @@
11
# Concurrent Ruby
2-
[![Gem Version](https://badge.fury.io/rb/concurrent-ruby.png)](http://badge.fury.io/rb/concurrent-ruby) [![Build Status](https://secure.travis-ci.org/jdantonio/concurrent-ruby.png)](https://travis-ci.org/jdantonio/concurrent-ruby?branch=master) [![Coverage Status](https://coveralls.io/repos/jdantonio/concurrent-ruby/badge.png)](https://coveralls.io/r/jdantonio/concurrent-ruby) [![Code Climate](https://codeclimate.com/github/jdantonio/concurrent-ruby.png)](https://codeclimate.com/github/jdantonio/concurrent-ruby) [![Dependency Status](https://gemnasium.com/jdantonio/concurrent-ruby.png)](https://gemnasium.com/jdantonio/concurrent-ruby)
2+
[![Gem Version](https://badge.fury.io/rb/concurrent-ruby.png)](http://badge.fury.io/rb/concurrent-ruby) [![Build Status](https://secure.travis-ci.org/jdantonio/concurrent-ruby.png)](https://travis-ci.org/jdantonio/concurrent-ruby?branch=master) [![Coverage Status](https://coveralls.io/repos/jdantonio/concurrent-ruby/badge.png)](https://coveralls.io/r/jdantonio/concurrent-ruby) [![Code Climate](https://codeclimate.com/github/jdantonio/concurrent-ruby.png)](https://codeclimate.com/github/jdantonio/concurrent-ruby) [![Inline docs](http://inch-pages.github.io/github/jdantonio/concurrent-ruby.png)](http://inch-pages.github.io/github/jdantonio/concurrent-ruby) [![Dependency Status](https://gemnasium.com/jdantonio/concurrent-ruby.png)](https://gemnasium.com/jdantonio/concurrent-ruby)
33

44
***NOTE:*** *A few API updates in v0.5.0 are not backward-compatible. Please see the [release notes](https://github.com/jdantonio/concurrent-ruby/wiki/API-Updates-in-v0.5.0).*
55

6+
<table>
7+
<tr>
8+
<td align="left" valign="top">
9+
<p>
610
Modern concurrency tools for Ruby. Inspired by
7-
[Erlang](http://www.erlang.org/doc/reference_manual/processes.html),
8-
[Clojure](http://clojure.org/concurrent_programming),
9-
[Scala](http://www.scala-lang.org/api/current/index.html#scala.actors.Actor),
10-
[Haskell](http://www.haskell.org/haskellwiki/Applications_and_libraries/Concurrency_and_parallelism#Concurrent_Haskell),
11-
[F#](http://blogs.msdn.com/b/dsyme/archive/2010/02/15/async-and-parallel-design-patterns-in-f-part-3-agents.aspx),
12-
[C#](http://msdn.microsoft.com/en-us/library/vstudio/hh191443.aspx),
13-
[Java](http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/package-summary.html),
11+
<a href="http://www.erlang.org/doc/reference_manual/processes.html">Erlang</a>,
12+
<a href="http://clojure.org/concurrent_programming">Clojure</a>,
13+
<a href="http://www.scala-lang.org/api/current/index.html#scala.actors.Actor">Scala</a>,
14+
<a href="http://www.haskell.org/haskellwiki/Applications_and_libraries/Concurrency_and_parallelism#Concurrent_Haskell">Haskell</a>,
15+
<a href="http://blogs.msdn.com/b/dsyme/archive/2010/02/15/async-and-parallel-design-patterns-in-f-part-3-agents.aspx">F#</a>,
16+
<a href="http://msdn.microsoft.com/en-us/library/vstudio/hh191443.aspx">C#</a>,
17+
<a href="http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/package-summary.html">Java</a>,
1418
and classic concurrency patterns.
15-
19+
</p>
20+
<p>
1621
The design goals of this gem are:
17-
18-
* Stay true to the spirit of the languages providing inspiration
19-
* But implement in a way that makes sense for Ruby
20-
* Keep the semantics as idiomatic Ruby as possible
21-
* Support features that make sense in Ruby
22-
* Exclude features that don't make sense in Ruby
23-
* Be small, lean, and loosely coupled
22+
<ul>
23+
<li>Stay true to the spirit of the languages providing inspiration</li>
24+
<li>But implement in a way that makes sense for Ruby</li>
25+
<li>Keep the semantics as idiomatic Ruby as possible</li>
26+
<li>Support features that make sense in Ruby</li>
27+
<li>Exclude features that don't make sense in Ruby</li>
28+
<li>Be small, lean, and loosely coupled</li>
29+
</ul>
30+
</p>
31+
</td>
32+
<td align="right" valign="top">
33+
<img src="https://raw.githubusercontent.com/wiki/jdantonio/concurrent-ruby/logo/concurrent-ruby-logo-300x300.png"/>
34+
</td>
35+
</tr>
36+
</table>
2437

2538
## Features & Documentation
2639

@@ -29,11 +42,13 @@ or the [API documentation](http://rubydoc.info/github/jdantonio/concurrent-ruby/
2942
for more information or join our [mailing list](http://groups.google.com/group/concurrent-ruby).
3043

3144
There are many concurrency abstractions in this library. These abstractions can be broadly categorized
32-
into several general categories:
45+
into several general groups:
3346

34-
* Asynchronous concurrency abstractions including [Actor](https://github.com/jdantonio/concurrent-ruby/wiki/Actor),
35-
[Agent](https://github.com/jdantonio/concurrent-ruby/wiki/Agent), [Channel](https://github.com/jdantonio/concurrent-ruby/wiki/Channel),
36-
[Future](https://github.com/jdantonio/concurrent-ruby/wiki/Future), [Promise](https://github.com/jdantonio/concurrent-ruby/wiki/Promise),
47+
* Asynchronous concurrency abstractions including
48+
[Async](https://github.com/jdantonio/concurrent-ruby/wiki/Async),
49+
[Agent](https://github.com/jdantonio/concurrent-ruby/wiki/Agent),
50+
[Future](https://github.com/jdantonio/concurrent-ruby/wiki/Future),
51+
[Promise](https://github.com/jdantonio/concurrent-ruby/wiki/Promise),
3752
[ScheculedTask](https://github.com/jdantonio/concurrent-ruby/wiki/ScheduledTask),
3853
and [TimerTask](https://github.com/jdantonio/concurrent-ruby/wiki/TimerTask)
3954
* Erlang-inspired [Supervisor](https://github.com/jdantonio/concurrent-ruby/wiki/Supervisor) and other lifecycle classes/mixins
@@ -53,73 +68,67 @@ This gem adheres to the rules of [semantic versioning](http://semver.org/).
5368

5469
### Supported Ruby versions
5570

56-
MRI 1.9.2, 1.9.3, 2.0, 2.1, JRuby (1.9 mode), and Rubinius 2.x. This library is pure Ruby and has no gem dependencies.
71+
MRI 1.9.2, 1.9.3, 2.0, 2.1, JRuby (1.9 mode), and Rubinius 2.x.
72+
This library is pure Ruby and has no gem dependencies.
5773
It should be fully compatible with any Ruby interpreter that is 1.9.x compliant.
5874

59-
### Example
75+
### Examples
6076

6177
Many more code examples can be found in the documentation for each class (linked above).
6278
This one simple example shows some of the power of this gem.
6379

6480
```ruby
6581
require 'concurrent'
66-
require 'faker'
67-
68-
class EchoActor < Concurrent::Actor
69-
def act(*message)
70-
puts "#{message} handled by #{self}"
82+
require 'thread' # for Queue
83+
require 'open-uri' # for open(uri)
84+
85+
class Ticker
86+
def get_year_end_closing(symbol, year)
87+
uri = "http://ichart.finance.yahoo.com/table.csv?s=#{symbol}&a=11&b=01&c=#{year}&d=11&e=31&f=#{year}&g=m"
88+
data = open(uri) {|f| f.collect{|line| line.strip } }
89+
data[1].split(',')[4].to_f
7190
end
7291
end
7392

74-
mailbox, pool = EchoActor.pool(5)
75-
76-
timer_proc = proc do
77-
mailbox.post(Faker::Company.bs)
78-
end
79-
80-
t1 = Concurrent::TimerTask.new(execution_interval: rand(5)+1, &timer_proc)
81-
t2 = Concurrent::TimerTask.new(execution_interval: rand(5)+1, &timer_proc)
82-
83-
overlord = Concurrent::Supervisor.new
84-
85-
overlord.add_worker(t1)
86-
overlord.add_worker(t2)
87-
pool.each{|actor| overlord.add_worker(actor)}
88-
89-
overlord.run!
90-
91-
#=> ["mesh proactive platforms"] handled by #<EchoActor:0x007fa5ac18bdf8>
92-
#=> ["maximize sticky portals"] handled by #<EchoActor:0x007fa5ac18bdd0>
93-
#=> ["morph bleeding-edge markets"] handled by #<EchoActor:0x007fa5ac18bd80>
94-
#=> ["engage clicks-and-mortar interfaces"] handled by #<EchoActor:0x007fa5ac18bd58>
95-
#=> ["monetize transparent infrastructures"] handled by #<EchoActor:0x007fa5ac18bd30>
96-
#=> ["morph sexy e-tailers"] handled by #<EchoActor:0x007fa5ac18bdf8>
97-
#=> ["exploit dot-com models"] handled by #<EchoActor:0x007fa5ac18bdd0>
98-
#=> ["incentivize virtual deliverables"] handled by #<EchoActor:0x007fa5ac18bd80>
99-
#=> ["enhance B2B models"] handled by #<EchoActor:0x007fa5ac18bd58>
100-
#=> ["envisioneer real-time architectures"] handled by #<EchoActor:0x007fa5ac18bd30>
101-
102-
overlord.stop
93+
# Future
94+
price = Concurrent::Future.execute{ Ticker.new.get_year_end_closing('TWTR', 2013) }
95+
price.state #=> :pending
96+
sleep(1) # do other stuff
97+
price.value #=> 63.65
98+
price.state #=> :fulfilled
99+
100+
# Promise
101+
prices = Concurrent::Promise.new{ puts Ticker.new.get_year_end_closing('AAPL', 2013) }.
102+
then{ puts Ticker.new.get_year_end_closing('MSFT', 2013) }.
103+
then{ puts Ticker.new.get_year_end_closing('GOOG', 2013) }.
104+
then{ puts Ticker.new.get_year_end_closing('AMZN', 2013) }.execute
105+
prices.state #=> :pending
106+
sleep(1) # do other stuff
107+
#=> 561.02
108+
#=> 37.41
109+
#=> 1120.71
110+
#=> 398.79
111+
112+
# ScheduledTask
113+
task = Concurrent::ScheduledTask.execute(2){ Ticker.new.get_year_end_closing('INTC', 2013) }
114+
task.state #=> :pending
115+
sleep(3) # do other stuff
116+
task.value #=> 25.96
117+
118+
# Async
119+
ticker = Ticker.new
120+
ticker.extend(Concurrent::Async)
121+
hpq = ticker.async.get_year_end_closing('HPQ', 2013)
122+
ibm = ticker.await.get_year_end_closing('IBM', 2013)
123+
hpq.value #=> 27.98
124+
ibm.value #=> 187.57
103125
```
104126

105-
### Disclaimer
106-
107-
Remember, *there is no silver bullet in concurrent programming.* Concurrency is hard.
108-
These tools will help ease the burden, but at the end of the day it is essential that you
109-
*know what you are doing.*
110-
111-
* Decouple business logic from concurrency logic
112-
* Test business logic separate from concurrency logic
113-
* Keep the intersection of business logic and concurrency and small as possible
114-
* Don't share mutable data unless absolutely necessary
115-
* Protect shared data as much as possible (prefer [immutability](https://github.com/harukizaemon/hamster))
116-
* Don't mix Ruby's [concurrency](http://ruby-doc.org/core-2.0.0/Thread.html)
117-
[primitives](http://www.ruby-doc.org/core-2.0.0/Mutex.html) with asynchronous concurrency libraries
118-
119127
## Contributors
120128

121129
* [Michele Della Torre](https://github.com/mighe)
122130
* [Chris Seaton](https://github.com/chrisseaton)
131+
* [Lucas Allan](https://github.com/lucasallan)
123132
* [Giuseppe Capizzi](https://github.com/gcapizzi)
124133
* [Brian Shirai](https://github.com/brixen)
125134
* [Chip Miller](https://github.com/chip-miller)
@@ -138,3 +147,6 @@ These tools will help ease the burden, but at the end of the day it is essential
138147

139148
*Concurrent Ruby* is Copyright &copy; 2013 [Jerry D'Antonio](https://twitter.com/jerrydantonio).
140149
It is free software released under the [MIT License](http://www.opensource.org/licenses/MIT).
150+
151+
The *Concurrent Ruby* logo was designed by [David Jones](https://twitter.com/zombyboy).
152+
It is Copyright &copy; 2014 Jerry D'Antonio. All Rights Reserved.

lib/concurrent.rb

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
require 'concurrent/version'
2+
require 'concurrent/configuration'
23

34
require 'concurrent/atomic'
45
require 'concurrent/count_down_latch'
@@ -10,14 +11,16 @@
1011

1112
require 'concurrent/actor'
1213
require 'concurrent/agent'
13-
require 'concurrent/channel'
14+
require 'concurrent/async'
1415
require 'concurrent/dataflow'
16+
require 'concurrent/delay'
1517
require 'concurrent/dereferenceable'
1618
require 'concurrent/event'
1719
require 'concurrent/future'
1820
require 'concurrent/mvar'
1921
require 'concurrent/obligation'
2022
require 'concurrent/postable'
23+
require 'concurrent/processor_count'
2124
require 'concurrent/promise'
2225
require 'concurrent/runnable'
2326
require 'concurrent/scheduled_task'
@@ -28,11 +31,12 @@
2831
require 'concurrent/tvar'
2932
require 'concurrent/utilities'
3033

31-
require 'concurrent/global_thread_pool'
32-
3334
require 'concurrent/cached_thread_pool'
3435
require 'concurrent/fixed_thread_pool'
3536
require 'concurrent/immediate_executor'
37+
require 'concurrent/per_thread_executor'
38+
require 'concurrent/thread_pool_executor'
39+
require 'concurrent/uses_global_thread_pool'
3640

3741
# Modern concurrency tools for Ruby. Inspired by Erlang, Clojure, Scala, Haskell,
3842
# F#, C#, Java, and classic concurrency patterns.

lib/concurrent/actor.rb

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,8 @@ module Concurrent
119119
#
120120
# ping << :pong
121121
#
122+
# @deprecated +Actor+ is being replaced with a completely new framework prior to v1.0.0
123+
#
122124
# @see http://ruby-doc.org/stdlib-2.0/libdoc/observer/rdoc/Observable.html
123125
class Actor
124126
include Observable
@@ -174,6 +176,8 @@ def initialize(queue)
174176
# #=> [6] handled by #<EchoActor:0x007fc8014fb8b8>
175177
# #=> [7] handled by #<EchoActor:0x007fc8014fb818>
176178
# #=> [8] handled by #<EchoActor:0x007fc8014fb890>
179+
#
180+
# @deprecated +Actor+ is being replaced with a completely new framework prior to v1.0.0
177181
def self.pool(count, *args, &block)
178182
raise ArgumentError.new('count must be greater than zero') unless count > 0
179183
mailbox = Queue.new
@@ -202,24 +206,32 @@ def self.pool(count, *args, &block)
202206
# @return [Object] the result obtained when the message is successfully processed
203207
#
204208
# @raise NotImplementedError unless overridden in the +Actor+ subclass
209+
#
210+
# @deprecated +Actor+ is being replaced with a completely new framework prior to v1.0.0
205211
#
206212
# @!visibility public
207213
def act(*message)
208214
raise NotImplementedError.new("#{self.class} does not implement #act")
209215
end
210216

211217
# @!visibility private
218+
#
219+
# @deprecated +Actor+ is being replaced with a completely new framework prior to v1.0.0
212220
def on_run # :nodoc:
213221
queue.clear
214222
end
215223

216224
# @!visibility private
225+
#
226+
# @deprecated +Actor+ is being replaced with a completely new framework prior to v1.0.0
217227
def on_stop # :nodoc:
218228
queue.clear
219229
queue.push(:stop)
220230
end
221231

222232
# @!visibility private
233+
#
234+
# @deprecated +Actor+ is being replaced with a completely new framework prior to v1.0.0
223235
def on_task # :nodoc:
224236
package = queue.pop
225237
return if package == :stop
@@ -247,6 +259,8 @@ def on_task # :nodoc:
247259
end
248260

249261
# @!visibility private
262+
#
263+
# @deprecated +Actor+ is being replaced with a completely new framework prior to v1.0.0
250264
def on_error(time, msg, ex) # :nodoc:
251265
end
252266
end

lib/concurrent/agent.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
require 'observer'
33

44
require 'concurrent/dereferenceable'
5-
require 'concurrent/global_thread_pool'
5+
require 'concurrent/uses_global_thread_pool'
66
require 'concurrent/utilities'
77

88
module Concurrent

0 commit comments

Comments
 (0)