Skip to content

Commit d239b74

Browse files
committed
Merge branch 'master' into tvars.
2 parents b2ad02b + 2988970 commit d239b74

Some content is hidden

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

81 files changed

+1668
-95332
lines changed

.ruby-gemset.sample

Lines changed: 0 additions & 1 deletion
This file was deleted.

.ruby-version.sample

Lines changed: 0 additions & 1 deletion
This file was deleted.

.switch

Lines changed: 0 additions & 7 deletions
This file was deleted.

Gemfile

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,15 @@ source 'https://rubygems.org'
33
gemspec
44

55
group :development do
6-
gem 'rake'
7-
gem 'countloc', :platforms => :mri
6+
gem 'rake', '~> 10.1.1'
7+
gem 'countloc', '~> 0.4.0', platforms: :mri
88
end
99

1010
group :testing do
11-
gem 'rspec'
12-
gem 'simplecov'
13-
gem 'coveralls', require: false
14-
gem 'yard'
15-
gem 'faker'
16-
gem 'timecop'
11+
gem 'rspec', '~> 2.14.1'
12+
gem 'simplecov', '~> 0.8.2'
13+
gem 'coveralls', '~> 0.7.0', require: false
14+
gem 'yard', '~> 0.8.7.3'
15+
gem 'faker', '~> 1.3.0'
16+
gem 'timecop', '~> 0.7.1'
1717
end

README.md

Lines changed: 26 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
1-
# 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) [![Dependency Status](https://gemnasium.com/jdantonio/concurrent-ruby.png)](https://gemnasium.com/jdantonio/concurrent-ruby)
1+
# 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)
3+
4+
***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).*
25

36
Modern concurrency tools for Ruby. Inspired by
47
[Erlang](http://www.erlang.org/doc/reference_manual/processes.html),
@@ -21,21 +24,28 @@ The design goals of this gem are:
2124

2225
## Features & Documentation
2326

24-
* Clojure-inspired [Agent](https://github.com/jdantonio/concurrent-ruby/blob/master/md/agent.md)
25-
* Clojure-inspired [Future](https://github.com/jdantonio/concurrent-ruby/blob/master/md/future.md)
26-
* Scala-inspired [Actor](https://github.com/jdantonio/concurrent-ruby/blob/master/md/actor.md)
27-
* JavaScript-inspired [Promise](https://github.com/jdantonio/concurrent-ruby/blob/master/md/promise.md)
28-
* Java-inspired [Thread Pools](https://github.com/jdantonio/concurrent-ruby/blob/master/md/thread_pool.md)
29-
* Old school [events](http://msdn.microsoft.com/en-us/library/windows/desktop/ms682655.aspx) from back in my Visual C++ days
30-
* Repeated task execution with Java-inspired [TimerTask](https://github.com/jdantonio/concurrent-ruby/blob/master/md/timer_task.md) service
31-
* Scheduled task execution with Java-inspired [ScheduledTask](https://github.com/jdantonio/concurrent-ruby/blob/master/md/scheduled_task.md) service
32-
* Erlang-inspired [Supervisor](https://github.com/jdantonio/concurrent-ruby/blob/master/md/supervisor.md) for managing long-running threads
33-
* Actor variant [Channel](https://github.com/jdantonio/concurrent-ruby/blob/master/md/channel.md)
34-
loosely based on the [MailboxProcessor](http://blogs.msdn.com/b/dsyme/archive/2010/02/15/async-and-parallel-design-patterns-in-f-part-3-agents.aspx)
35-
agent in [F#](http://msdn.microsoft.com/en-us/library/ee370357.aspx)
36-
* [Dataflow](https://github.com/jdantonio/concurrent-ruby/blob/master/md/dataflow.md) loosely based on the syntax of Akka and Habanero Java
37-
* [MVar](https://github.com/jdantonio/concurrent-ruby/blob/master/md/mvar.md) inspired by Haskell
38-
* [Thread local variables](https://github.com/jdantonio/concurrent-ruby/blob/master/md/threadlocalvar.md) with default value
27+
Please see the [Concurrent Ruby Wiki](https://github.com/jdantonio/concurrent-ruby/wiki)
28+
or the [API documentation](http://rubydoc.info/github/jdantonio/concurrent-ruby/master/frames)
29+
for more information or join our [mailing list](http://groups.google.com/group/concurrent-ruby).
30+
31+
There are many concurrency abstractions in this library. These abstractions can be broadly categorized
32+
into several general categories:
33+
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),
37+
[ScheculedTask](https://github.com/jdantonio/concurrent-ruby/wiki/ScheduledTask),
38+
and [TimerTask](https://github.com/jdantonio/concurrent-ruby/wiki/TimerTask)
39+
* Erlang-inspired [Supervisor](https://github.com/jdantonio/concurrent-ruby/wiki/Supervisor) and other lifecycle classes/mixins
40+
for managing long-running threads
41+
* Thread-safe variables including [M-Structures](https://github.com/jdantonio/concurrent-ruby/wiki/MVar-(M-Structure)),
42+
[I-Structures](https://github.com/jdantonio/concurrent-ruby/wiki/IVar-(I-Structure)),
43+
[thread-local variables](https://github.com/jdantonio/concurrent-ruby/wiki/ThreadLocalVar),
44+
and atomic counters
45+
* Thread synchronization classes and algorithms including [dataflow](https://github.com/jdantonio/concurrent-ruby/wiki/Dataflow),
46+
timeout, condition, countdown latch, dependency counter, and event
47+
* Java-inspired [thread pools](https://github.com/jdantonio/concurrent-ruby/wiki/Thread%20Pools)
48+
* And many more...
3949

4050
### Semantic Versioning
4151

@@ -124,24 +134,6 @@ These tools will help ease the burden, but at the end of the day it is essential
124134
4. Push to the branch (`git push origin my-new-feature`)
125135
5. Create new Pull Request
126136

127-
### Conference Presentations
128-
129-
I've given several conference presentations on concurrent programming with this gem.
130-
Check them out:
131-
132-
* ["Advanced Concurrent Programming in Ruby"](http://rubyconf.org/program#jerry-dantonio)
133-
at [RubyConf 2013](http://rubyconf.org/)
134-
used [this](https://github.com/jdantonio/concurrent-ruby-presentation) version of the presentation
135-
and is available for viewing on [Confreaks](http://www.confreaks.com/videos/2872-rubyconf2013-advanced-concurrent-programming-in-ruby)
136-
* ["Advanced Multithreading in Ruby"](http://cascadiaruby.com/#advanced-multithreading-in-ruby)
137-
at [Cascadia Ruby 2013](http://cascadiaruby.com/)
138-
used [this](https://github.com/jdantonio/concurrent-ruby-presentation/tree/cascadia-ruby-2013) version of the presentation
139-
and is available for viewing on [Confreaks](http://www.confreaks.com/videos/2790-cascadiaruby2013-advanced-multithreading-in-ruby)
140-
* [Cleveland Ruby Brigade](http://www.meetup.com/ClevelandRuby/events/149981942/) meetup in December of 2013
141-
used [this](https://github.com/jdantonio/concurrent-ruby-presentation/releases/tag/clerb-dec-2013) version of the presentation
142-
* I'll be giving ["Advanced Concurrent Programming in Ruby"](http://codemash.org/sessions)
143-
at [CodeMash 2014](http://codemash.org/)
144-
145137
## License and Copyright
146138

147139
*Concurrent Ruby* is Copyright © 2013 [Jerry D'Antonio](https://twitter.com/jerrydantonio).

lib/concurrent.rb

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
require 'concurrent/version'
22

3-
require 'concurrent/atomic_counter'
3+
require 'concurrent/atomic'
44
require 'concurrent/count_down_latch'
55
require 'concurrent/condition'
66
require 'concurrent/copy_on_notify_observer_set'
77
require 'concurrent/copy_on_write_observer_set'
88
require 'concurrent/safe_task_executor'
9+
require 'concurrent/ivar'
910

1011
require 'concurrent/actor'
1112
require 'concurrent/agent'
12-
require 'concurrent/contract'
1313
require 'concurrent/channel'
1414
require 'concurrent/dataflow'
1515
require 'concurrent/dereferenceable'
@@ -23,7 +23,7 @@
2323
require 'concurrent/scheduled_task'
2424
require 'concurrent/stoppable'
2525
require 'concurrent/supervisor'
26-
require 'concurrent/threadlocalvar'
26+
require 'concurrent/thread_local_var'
2727
require 'concurrent/timer_task'
2828
require 'concurrent/tvar'
2929
require 'concurrent/utilities'

lib/concurrent/actor.rb

Lines changed: 29 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -19,36 +19,36 @@ module Concurrent
1919
#
2020
# An independent, concurrent, single-purpose, computational entity that communicates exclusively via message passing.
2121
#
22-
# The `Concurrent::Actor` class in this library is based solely on the
22+
# The +Concurrent::Actor+ class in this library is based solely on the
2323
# {http://www.scala-lang.org/api/current/index.html#scala.actors.Actor Actor} trait
2424
# defined in the Scala standard library. It does not implement all the features of
25-
# Scala's `Actor` but its behavior for what *has* been implemented is nearly identical.
25+
# Scala's +Actor+ but its behavior for what *has* been implemented is nearly identical.
2626
# The excluded features mostly deal with Scala's message semantics, strong typing,
2727
# and other characteristics of Scala that don't really apply to Ruby.
2828
#
29-
# Unlike most of the abstractions in this library, `Actor` takes an *object-oriented*
29+
# Unlike many of the abstractions in this library, +Actor+ takes an *object-oriented*
3030
# approach to asynchronous concurrency, rather than a *functional programming*
3131
# approach.
3232
#
33-
# Because `Actor` mixes in the `Concurrent::Runnable` module subclasses have access to
34-
# the `#on_error` method and can override it to implement custom error handling. The
35-
# `Actor` base class does not use `#on_error` so as to avoid conflit with subclasses
36-
# which override it. Generally speaking, `#on_error` should not be used. The `Actor`
33+
# Because +Actor+ mixes in the +Concurrent::Runnable+ module subclasses have access to
34+
# the +#on_error+ method and can override it to implement custom error handling. The
35+
# +Actor+ base class does not use +#on_error+ so as to avoid conflit with subclasses
36+
# which override it. Generally speaking, +#on_error+ should not be used. The +Actor+
3737
# base class provides concictent, reliable, and robust error handling already, and
3838
# error handling specifics are tied to the message posting method. Incorrect behavior
39-
# in an `#on_error` override can lead to inconsistent `Actor` behavior that may lead
39+
# in an +#on_error+ override can lead to inconsistent +Actor+ behavior that may lead
4040
# to confusion and difficult debugging.
4141
#
42-
# The `Actor` superclass mixes in the Ruby standard library
42+
# The +Actor+ superclass mixes in the Ruby standard library
4343
# {http://ruby-doc.org/stdlib-2.0/libdoc/observer/rdoc/Observable.html Observable}
4444
# module to provide consistent callbacks upon message processing completion. The normal
45-
# `Observable` methods, including `#add_observer` behave normally. Once an observer
46-
# is added to an `Actor` it will be notified of all messages processed *after*
45+
# +Observable+ methods, including +#add_observer+ behave normally. Once an observer
46+
# is added to an +Actor+ it will be notified of all messages processed *after*
4747
# addition. Notification will *not* occur for any messages that have already been
4848
# processed.
4949
#
5050
# Observers will be notified regardless of whether the message processing is successful
51-
# or not. The `#update` method of the observer will receive four arguments. The
51+
# or not. The +#update+ method of the observer will receive four arguments. The
5252
# appropriate method signature is:
5353
#
5454
# def update(time, message, result, reason)
@@ -57,8 +57,8 @@ module Concurrent
5757
#
5858
# * The time that message processing was completed
5959
# * An array containing all elements of the original message, in order
60-
# * The result of the call to `#act` (will be `nil` if an exception was raised)
61-
# * Any exception raised by `#act` (or `nil` if message processing was successful)
60+
# * The result of the call to +#act+ (will be +nil+ if an exception was raised)
61+
# * Any exception raised by +#act+ (or +nil+ if message processing was successful)
6262
#
6363
# @example Actor Ping Pong
6464
# class Ping < Concurrent::Actor
@@ -140,10 +140,10 @@ def initialize(queue)
140140

141141
# Create a pool of actors that share a common mailbox.
142142
#
143-
# Every `Actor` instance operates on its own thread. When one thread isn't enough capacity
144-
# to manage all the messages being sent to an `Actor` a *pool* can be used instead. A pool
145-
# is a collection of `Actor` instances, all of the same type, that shate a message queue.
146-
# Messages from other threads are all sent to a single queue against which all `Actor`s
143+
# Every +Actor+ instance operates on its own thread. When one thread isn't enough capacity
144+
# to manage all the messages being sent to an +Actor+ a *pool* can be used instead. A pool
145+
# is a collection of +Actor+ instances, all of the same type, that shate a message queue.
146+
# Messages from other threads are all sent to a single queue against which all +Actor+s
147147
# load balance.
148148
#
149149
# @param [Integer] count the number of actors in the pool
@@ -152,7 +152,7 @@ def initialize(queue)
152152
# @return [Array] two-element array with the shared mailbox as the first element
153153
# and an array of actors as the second element
154154
#
155-
# @raise ArgumentError if `count` is zero or less
155+
# @raise ArgumentError if +count+ is zero or less
156156
#
157157
# @example
158158
# class EchoActor < Concurrent::Actor
@@ -191,35 +191,35 @@ def self.pool(count, *args, &block)
191191

192192
protected
193193

194-
# Actors are defined by subclassing the `Concurrent::Actor` class and overriding the
195-
# #act method. The #act method can have any signature/arity but `def act(*args)`
194+
# Actors are defined by subclassing the +Concurrent::Actor+ class and overriding the
195+
# #act method. The #act method can have any signature/arity but +def act(*args)+
196196
# is the most flexible and least error-prone signature. The #act method is called in
197-
# response to a message being post to the `Actor` instance (see *Behavior* below).
197+
# response to a message being post to the +Actor+ instance (see *Behavior* below).
198198
#
199199
# @param [Array] message one or more arguments representing the message sent to the
200200
# actor via one of the Concurrent::Postable methods
201201
#
202202
# @return [Object] the result obtained when the message is successfully processed
203203
#
204-
# @raise NotImplementedError unless overridden in the `Actor` subclass
204+
# @raise NotImplementedError unless overridden in the +Actor+ subclass
205205
#
206206
# @!visibility public
207207
def act(*message)
208208
raise NotImplementedError.new("#{self.class} does not implement #act")
209209
end
210210

211-
# @private
211+
# @!visibility private
212212
def on_run # :nodoc:
213213
queue.clear
214214
end
215215

216-
# @private
216+
# @!visibility private
217217
def on_stop # :nodoc:
218218
queue.clear
219219
queue.push(:stop)
220220
end
221221

222-
# @private
222+
# @!visibility private
223223
def on_task # :nodoc:
224224
package = queue.pop
225225
return if package == :stop
@@ -235,8 +235,8 @@ def on_task # :nodoc:
235235
if notifier.is_a?(Event) && ! notifier.set?
236236
package.handler.push(result || ex)
237237
package.notifier.set
238-
elsif package.handler.is_a?(Contract)
239-
package.handler.complete(result, ex)
238+
elsif package.handler.is_a?(IVar)
239+
package.handler.complete(! result.nil?, result, ex)
240240
elsif package.handler.respond_to?(:post) && ex.nil?
241241
package.handler.post(result)
242242
end
@@ -246,7 +246,7 @@ def on_task # :nodoc:
246246
end
247247
end
248248

249-
# @private
249+
# @!visibility private
250250
def on_error(time, msg, ex) # :nodoc:
251251
end
252252
end

0 commit comments

Comments
 (0)