Skip to content

Commit

Permalink
Merge pull request #100 from ruby-concurrency/actress
Browse files Browse the repository at this point in the history
Actress post release fixes
  • Loading branch information
jdantonio committed Jun 14, 2014
2 parents 49417cb + c0ce8b6 commit 46e7bb0
Show file tree
Hide file tree
Showing 35 changed files with 967 additions and 244 deletions.
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ tests.txt
.ruby-gemset
.bundle/*
.yardoc/*
doc/*
yardoc/*
tmp/*
man/*
*.tmproj
Expand Down
1 change: 1 addition & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,4 @@ matrix:
- rvm: ruby-head
- rvm: jruby-head
- rvm: 1.9.3
script: "bundle exec rspec --color --backtrace --seed 1 --format documentation ./spec"
14 changes: 13 additions & 1 deletion .yardopts
Original file line number Diff line number Diff line change
@@ -1 +1,13 @@
--protected --no-private --embed-mixins --output-dir ./doc --markup markdown
--protected
--no-private
--embed-mixins
--output-dir ./yardoc
--markup markdown
--title=Concurrent Ruby
--template default
--template-path ./yard-template

./lib/**/*.rb
-
README.md
LICENSE.txt
1 change: 1 addition & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ group :development do
gem 'countloc', '~> 0.4.0', platforms: :mri
gem 'yard', '~> 0.8.7.4'
gem 'inch', '~> 0.4.1', platforms: :mri
gem 'redcarpet', platforms: :mri # understands github markdown
end

group :testing do
Expand Down
File renamed without changes.
73 changes: 38 additions & 35 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,57 +2,59 @@
[![Gem Version](https://badge.fury.io/rb/concurrent-ruby.png)](http://badge.fury.io/rb/concurrent-ruby) [![Build Status](https://travis-ci.org/ruby-concurrency/concurrent-ruby.svg?branch=master)](https://travis-ci.org/ruby-concurrency/concurrent-ruby) [![Coverage Status](https://coveralls.io/repos/ruby-concurrency/concurrent-ruby/badge.png)](https://coveralls.io/r/ruby-concurrency/concurrent-ruby) [![Code Climate](https://codeclimate.com/github/ruby-concurrency/concurrent-ruby.png)](https://codeclimate.com/github/ruby-concurrency/concurrent-ruby) [![Inline docs](http://inch-ci.org/github/ruby-concurrency/concurrent-ruby.png)](http://inch-ci.org/github/ruby-concurrency/concurrent-ruby) [![Dependency Status](https://gemnasium.com/ruby-concurrency/concurrent-ruby.png)](https://gemnasium.com/ruby-concurrency/concurrent-ruby)

<table>
<tr>
<td align="left" valign="top">
<p>
Modern concurrency tools for Ruby. Inspired by
<a href="http://www.erlang.org/doc/reference_manual/processes.html">Erlang</a>,
<a href="http://clojure.org/concurrent_programming">Clojure</a>,
<a href="http://www.scala-lang.org/api/current/index.html#scala.actors.Actor">Scala</a>,
<a href="http://www.haskell.org/haskellwiki/Applications_and_libraries/Concurrency_and_parallelism#Concurrent_Haskell">Haskell</a>,
<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>,
<a href="http://msdn.microsoft.com/en-us/library/vstudio/hh191443.aspx">C#</a>,
<a href="http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/package-summary.html">Java</a>,
and classic concurrency patterns.
</p>
<p>
The design goals of this gem are:
<ul>
<li>Be an 'unopinionated' toolbox that provides useful utilities without debating which is better or why</li>
<li>Remain free of external gem dependencies</li>
<li>Stay true to the spirit of the languages providing inspiration</li>
<li>But implement in a way that makes sense for Ruby</li>
<li>Keep the semantics as idiomatic Ruby as possible</li>
<li>Support features that make sense in Ruby</li>
<li>Exclude features that don't make sense in Ruby</li>
<li>Be small, lean, and loosely coupled</li>
</ul>
</p>
</td>
<td align="right" valign="top">
<img src="https://raw.githubusercontent.com/wiki/ruby-concurrency/concurrent-ruby/logo/concurrent-ruby-logo-300x300.png"/>
</td>
</tr>
<tr>
<td align="left" valign="top">
<p>
Modern concurrency tools for Ruby. Inspired by
<a href="http://www.erlang.org/doc/reference_manual/processes.html">Erlang</a>,
<a href="http://clojure.org/concurrent_programming">Clojure</a>,
<a href="http://www.scala-lang.org/api/current/index.html#scala.actors.Actor">Scala</a>,
<a href="http://www.haskell.org/haskellwiki/Applications_and_libraries/Concurrency_and_parallelism#Concurrent_Haskell">Haskell</a>,
<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>,
<a href="http://msdn.microsoft.com/en-us/library/vstudio/hh191443.aspx">C#</a>,
<a href="http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/package-summary.html">Java</a>,
and classic concurrency patterns.
</p>
<p>
The design goals of this gem are:
<ul>
<li>Be an 'unopinionated' toolbox that provides useful utilities without debating which is better or why</li>
<li>Remain free of external gem dependencies</li>
<li>Stay true to the spirit of the languages providing inspiration</li>
<li>But implement in a way that makes sense for Ruby</li>
<li>Keep the semantics as idiomatic Ruby as possible</li>
<li>Support features that make sense in Ruby</li>
<li>Exclude features that don't make sense in Ruby</li>
<li>Be small, lean, and loosely coupled</li>
</ul>
</p>
</td>
<td align="right" valign="top">
<img src="https://raw.githubusercontent.com/wiki/ruby-concurrency/concurrent-ruby/logo/concurrent-ruby-logo-300x300.png"/>
</td>
</tr>
</table>

### Install
## Install

```shell
gem install concurrent-ruby
```

or add the following line to Gemfile:

```ruby
gem 'concurrent-ruby'
```

and run `bundle install` from your shell.

*NOTE: There is an old gem from 2007 called "concurrent" that does not appear to be under active development. That isn't us. Please do not run* `gem install concurrent`*. It is not the droid you are looking for.*
_NOTE: There is an old gem from 2007 called "concurrent" that does not appear to be under active development. That isn't us. Please do not run* `gem install concurrent`*. It is not the droid you are looking for._

## Features & Documentation

Please see the [Concurrent Ruby Wiki](https://github.com/ruby-concurrency/concurrent-ruby/wiki)
or the [API documentation](http://rubydoc.info/github/ruby-concurrency/concurrent-ruby/master/frames)
or the [API documentation](http://ruby-concurrency.github.io/concurrent-ruby/frames.html))
for more information or join our [mailing list](http://groups.google.com/group/concurrent-ruby).

There are many concurrency abstractions in this library. These abstractions can be broadly categorized
Expand All @@ -74,6 +76,7 @@ into several general groups:
* Thread synchronization classes and algorithms including [dataflow](https://github.com/ruby-concurrency/concurrent-ruby/wiki/Dataflow),
timeout, condition, countdown latch, dependency counter, and event
* Java-inspired [thread pools](https://github.com/ruby-concurrency/concurrent-ruby/wiki/Thread%20Pools)
* New fast light-weighted [Actor model](http://ruby-concurrency.github.io/concurrent-ruby/frames.html#!Concurrent/Actress.html) implementation.
* And many more...

### Semantic Versioning
Expand All @@ -91,7 +94,7 @@ It should be fully compatible with any interpreter that is compliant with Ruby 1
Many more code examples can be found in the documentation for each class (linked above).
This one simple example shows some of the power of this gem.

```ruby
```ruby
require 'concurrent'
require 'thread' # for Queue
require 'open-uri' # for open(uri)
Expand Down
96 changes: 96 additions & 0 deletions doc/actress/celluloid_benchmark.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
require 'benchmark'
require 'concurrent/actress'
Concurrent::Actress.i_know_it_is_experimental!
require 'celluloid'
require 'celluloid/autostart'

logger = Logger.new($stderr)
logger.level = Logger::INFO
Concurrent.configuration.logger = lambda do |level, progname, message = nil, &block|
logger.add level, message, progname, &block
end

scale = 1
ADD_TO = (100 * scale).to_i
counts_size = (500 * scale).to_i
adders_size = (500 * scale).to_i

class Counter
include Celluloid

def initialize(adders, i)
@adders = adders
@i = i
end

def counting(count, ivar)
if count < ADD_TO
@adders[(@i+1) % @adders.size].counting count+1, ivar
else
ivar.set count
end
end
end

threads = []

Benchmark.bmbm(10) do |b|
[2, adders_size, adders_size*2, adders_size*3].each do |adders_size|

b.report(format('%5d %4d %s', ADD_TO*counts_size, adders_size, 'actress')) do
counts = Array.new(counts_size) { [0, Concurrent::IVar.new] }
adders = Array.new(adders_size) do |i|
Concurrent::Actress::AdHoc.spawn("adder#{i}") do
lambda do |(count, ivar)|
if count.nil?
terminate!
else
if count < ADD_TO
adders[(i+1) % adders_size].tell [count+1, ivar]
else
ivar.set count
end
end
end
end
end

counts.each_with_index do |count, i|
adders[i % adders_size].tell count
end

counts.each do |count, ivar|
raise unless ivar.value >= ADD_TO
end

threads << Thread.list.size

adders.each { |a| a << [nil, nil] }
end

b.report(format('%5d %4d %s', ADD_TO*counts_size, adders_size, 'celluloid')) do
counts = []
counts_size.times { counts << [0, Concurrent::IVar.new] }

adders = []
adders_size.times do |i|
adders << Counter.new(adders, i)
end

counts.each_with_index do |count, i|
adders[i % adders_size].counting *count
end

counts.each do |count, ivar|
raise unless ivar.value >= ADD_TO
end

threads << Thread.list.size

adders.each(&:terminate)
end
end
end

p threads

75 changes: 75 additions & 0 deletions doc/actress/format.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
require 'rubygems'
require 'bundler/setup'
require 'pry'
require 'pp'

input_paths = if ARGV.empty?
Dir.glob("#{File.dirname(__FILE__)}/*.in.rb")
else
ARGV
end.map { |p| File.expand_path p }

input_paths.each_with_index do |input_path, i|

pid = fork do
require_relative 'init.rb'

begin
output_path = input_path.gsub /\.in\.rb$/, '.out.rb'
input = File.readlines(input_path)

chunks = []
line = ''

while !input.empty?
line += input.shift
if Pry::Code.complete_expression? line
chunks << line
line = ''
end
end

raise unless line.empty?

chunks.map! { |chunk| [chunk, [chunk.split($/).size, 1].max] }
environment = Module.new.send :binding
evaluate = ->(code, line) do
eval(code, environment, input_path, line)
end

indent = 50

line_count = 1
output = ''
chunks.each do |chunk, lines|
result = evaluate.(chunk, line_count)
unless chunk.strip.empty? || chunk =~ /\A *#/
pre_lines = chunk.lines.to_a
last_line = pre_lines.pop
output << pre_lines.join

if last_line =~ /\#$/
output << last_line.gsub(/\#$/, '')
else
if last_line.size < indent && result.inspect.size < indent
output << "%-#{indent}s %s" % [last_line.chomp, "# => #{result.inspect}\n"]
else
output << last_line << " # => #{result.inspect}\n"
end
end
else
output << chunk
end
line_count += lines
end

puts "#{input_path}\n -> #{output_path}"
#puts output
File.write(output_path, output)
rescue => ex
puts "#{ex} (#{ex.class})\n#{ex.backtrace * "\n"}"
end
end

Process.wait pid
end
2 changes: 2 additions & 0 deletions doc/actress/init.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
require 'concurrent/actress'
Concurrent::Actress.i_know_it_is_experimental!
Loading

0 comments on commit 46e7bb0

Please sign in to comment.