Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 20 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,15 +52,13 @@ This library contains a variety of concurrency abstractions at high and low leve

### High-level, general-purpose asynchronous concurrency abstractions

* [Actor](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/Actor.html): Implements the Actor Model, where concurrent actors exchange messages.
* [Agent](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/Agent.html): A single atomic value that represents an identity.
* [Async](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/Async.html): A mixin module that provides simple asynchronous behavior to any standard class/object or object.
* [Future](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/Future.html): An asynchronous operation that produces a value.
* [Dataflow](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent.html#dataflow-class_method): Built on Futures, Dataflow allows you to create a task that will be scheduled when all of its data dependencies are available.
* [Promise](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/Promise.html): Similar to Futures, with more features.
* [ScheduledTask](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/ScheduledTask.html): Like a Future scheduled for a specific future time.
* [TimerTask](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/TimerTask.html): A Thread that periodically wakes up to perform work at regular intervals.
* [Channel](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/Channel.html): Communicating Sequential Processes (CSP).

### Java-inspired ThreadPools and other executors

Expand Down Expand Up @@ -90,6 +88,19 @@ This library contains a variety of concurrency abstractions at high and low leve
* [Software transactional memory](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/TVar.html) (TVar)
* [ReadWriteLock](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/ReadWriteLock.html)

### Edge features

They are available in the `concurrent-ruby-edge` companion gem, install with `gem install concurrent-ruby-edge`.

These features are under active development and may change frequently. They are expected not to
keep backward compatibility (there may also lack tests and documentation). Semantic versions will
be obeyed though. Features developed in `concurrent-ruby-edge` are expected to move to `concurrent-ruby` when final.

* [Actor](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/Actor.html):
Implements the Actor Model, where concurrent actors exchange messages.
* [Channel](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/Channel.html):
Communicating Sequential Processes (CSP).

## Usage

All abstractions within this gem can be loaded simply by requiring it:
Expand All @@ -105,9 +116,7 @@ require 'concurrent' # everything

# groups

require 'concurrent/actor' # Concurrent::Actor and supporting code
require 'concurrent/atomics' # atomic and thread synchronization classes
require 'concurrent/channels' # Concurrent::Channel and supporting code
require 'concurrent/executors' # Thread pools and other executors
require 'concurrent/utilities' # utility methods such as processor count and timers

Expand All @@ -127,6 +136,11 @@ require 'concurrent/promise' # Concurrent::Promise
require 'concurrent/scheduled_task' # Concurrent::ScheduledTask
require 'concurrent/timer_task' # Concurrent::TimerTask
require 'concurrent/tvar' # Concurrent::TVar

# experimental - available in `concurrent-ruby-edge` companion gem

require 'concurrent/actor' # Concurrent::Actor and supporting code
require 'concurrent/channel ' # Concurrent::Channel and supporting code
```

## Installation
Expand All @@ -147,8 +161,8 @@ and run `bundle install` from your shell.

Potential performance improvements may be achieved under MRI by installing optional C extensions.
To minimize installation errors the C extensions are available in the `concurrent-ruby-ext` extension
gem. The extension gem lists `concurrent-ruby` as a dependency so it is not necessary to install both.
Simply install the extension gen:
gem. `concurrent-ruby` and `concurrent-ruby-ext` are always released together with same version.
Simply install the extension gen too:

```ruby
gem install concurrent-ruby-ext
Expand Down
39 changes: 27 additions & 12 deletions Rakefile
Original file line number Diff line number Diff line change
@@ -1,23 +1,27 @@
#!/usr/bin/env rake

require_relative './lib/concurrent/version'
require_relative './lib/extension_helper'

## load the two gemspec files
CORE_GEMSPEC = Gem::Specification.load('concurrent-ruby.gemspec')
EXT_GEMSPEC = Gem::Specification.load('concurrent-ruby-ext.gemspec')
EDGE_GEMSPEC = Gem::Specification.load('concurrent-ruby-edge.gemspec')

## constants used for compile/build tasks

GEM_NAME = 'concurrent-ruby'
EXTENSION_NAME = 'extension'
EXT_NAME = 'extension'
EDGE_NAME = 'edge'
JAVA_EXT_NAME = 'concurrent_ruby_ext'

if Concurrent.jruby?
CORE_GEM = "#{GEM_NAME}-#{Concurrent::VERSION}-java.gem"
else
CORE_GEM = "#{GEM_NAME}-#{Concurrent::VERSION}.gem"
EXTENSION_GEM = "#{GEM_NAME}-ext-#{Concurrent::VERSION}.gem"
EXT_GEM = "#{GEM_NAME}-ext-#{Concurrent::VERSION}.gem"
NATIVE_GEM = "#{GEM_NAME}-ext-#{Concurrent::VERSION}-#{Gem::Platform.new(RUBY_PLATFORM)}.gem"
EDGE_GEM = "#{GEM_NAME}-edge-#{Concurrent::EDGE_VERSION}.gem"
end

## safely load all the rake tasks in the `tasks` directory
Expand Down Expand Up @@ -49,7 +53,7 @@ elsif Concurrent.allow_c_extensions?
## create the compile tasks for the extension gem
require 'rake/extensiontask'

Rake::ExtensionTask.new(EXTENSION_NAME, EXT_GEMSPEC) do |ext|
Rake::ExtensionTask.new(EXT_NAME, EXT_GEMSPEC) do |ext|
ext.ext_dir = 'ext/concurrent'
ext.lib_dir = 'lib/concurrent'
ext.source_pattern = '*.{c,h}'
Expand All @@ -63,9 +67,9 @@ elsif Concurrent.allow_c_extensions?
'x64-mingw32' => 'x86_64-w64-mingw32'
}
platforms.each do |platform, prefix|
task "copy:#{EXTENSION_NAME}:#{platform}:#{ruby_version}" do |t|
task "copy:#{EXT_NAME}:#{platform}:#{ruby_version}" do |t|
%w[lib tmp/#{platform}/stage/lib].each do |dir|
so_file = "#{dir}/#{ruby_version[/^\d+\.\d+/]}/#{EXTENSION_NAME}.so"
so_file = "#{dir}/#{ruby_version[/^\d+\.\d+/]}/#{EXT_NAME}.so"
if File.exists?(so_file)
sh "#{prefix}-strip -S #{so_file}"
end
Expand Down Expand Up @@ -94,7 +98,11 @@ end

namespace :build do

build_deps = [:clean]
task :mkdir_pkg do
mkdir_p 'pkg'
end

build_deps = [:clean, 'build:mkdir_pkg']
build_deps << :compile if Concurrent.jruby?

desc "Build #{CORE_GEM} into the pkg directory"
Expand All @@ -104,17 +112,24 @@ namespace :build do
end

unless Concurrent.jruby?
desc "Build #{EXTENSION_GEM} into the pkg directory"
task :ext => [:clean] do

desc "Build #{EDGE_GEM} into the pkg directory"
task :edge => 'build:mkdir_pkg' do
sh "gem build #{EDGE_GEMSPEC.name}.gemspec"
sh 'mv *.gem pkg/'
end

desc "Build #{EXT_GEM} into the pkg directory"
task :ext => build_deps do
sh "gem build #{EXT_GEMSPEC.name}.gemspec"
sh 'mv *.gem pkg/'
end
end

if Concurrent.allow_c_extensions?
desc "Build #{NATIVE_GEM} into the pkg directory"
task :native do
sh "gem compile pkg/#{EXTENSION_GEM}"
task :native => 'build:mkdir_pkg' do
sh "gem compile pkg/#{EXT_GEM}"
sh 'mv *.gem pkg/'
end
end
Expand All @@ -124,8 +139,8 @@ if Concurrent.jruby?
desc 'Build JRuby-specific core gem (alias for `build:core`)'
task :build => ['build:core']
else
desc 'Build core and extension gems'
task :build => ['build:core', 'build:ext']
desc 'Build core, extension, and edge gems'
task :build => ['build:core', 'build:ext', 'build:edge']
end

## the RSpec task that compiles extensions when available
Expand Down
31 changes: 31 additions & 0 deletions concurrent-ruby-edge.gemspec
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
$:.push File.join(File.dirname(__FILE__), 'lib')

require 'concurrent/version'
require 'concurrent/file_map'

Gem::Specification.new do |s|
git_files = `git ls-files`.split("\n")

s.name = 'concurrent-ruby-edge'
s.version = Concurrent::EDGE_VERSION
s.platform = Gem::Platform::RUBY
s.authors = ["Jerry D'Antonio", 'The Ruby Concurrency Team']
s.email = ['[email protected]', '[email protected]']
s.homepage = 'http://www.concurrent-ruby.com'
s.summary = 'Edge features and additions to the concurrent-ruby gem.'
s.license = 'MIT'
s.date = Time.now.strftime('%Y-%m-%d')
s.files = Concurrent::FILE_MAP.fetch :edge
s.extra_rdoc_files = Dir['README*', 'LICENSE*']
s.require_paths = ['lib']
s.description = <<-TXT
These features are under active development and may change frequently. They are expected not to
keep backward compatibility (there may also lack tests and documentation). Semantic versions will
be obeyed though. Features developed in `concurrent-ruby-edge` are expected to move to `concurrent-ruby` when final.
Please see http://concurrent-ruby.com for more information.
TXT

s.required_ruby_version = '>= 1.9.3'

s.add_runtime_dependency 'concurrent-ruby', "~> #{Concurrent::VERSION}"
end
33 changes: 17 additions & 16 deletions concurrent-ruby.gemspec
Original file line number Diff line number Diff line change
@@ -1,29 +1,30 @@
$:.push File.join(File.dirname(__FILE__), 'lib')

require 'concurrent/version'
require 'concurrent/file_map'

Gem::Specification.new do |s|
s.name = 'concurrent-ruby'
s.version = Concurrent::VERSION
s.platform = Gem::Platform::RUBY
s.author = "Jerry D'Antonio"
s.email = '[email protected]'
s.homepage = 'http://www.concurrent-ruby.com'
s.summary = 'Modern concurrency tools for Ruby. Inspired by Erlang, Clojure, Scala, Haskell, F#, C#, Java, and classic concurrency patterns.'
s.license = 'MIT'
s.date = Time.now.strftime('%Y-%m-%d')
git_files = `git ls-files`.split("\n")

s.description = <<-EOF
Modern concurrency tools including agents, futures, promises, thread pools, actors, supervisors, and more.
Inspired by Erlang, Clojure, Go, JavaScript, actors, and classic concurrency patterns.
EOF

s.files = Dir['lib/**/*.rb']
s.name = 'concurrent-ruby'
s.version = Concurrent::VERSION
s.platform = Gem::Platform::RUBY
s.authors = ["Jerry D'Antonio", 'The Ruby Concurrency Team']
s.email = ['[email protected]', '[email protected]']
s.homepage = 'http://www.concurrent-ruby.com'
s.summary = 'Modern concurrency tools for Ruby. Inspired by Erlang, Clojure, Scala, Haskell, F#, C#, Java, and classic concurrency patterns.'
s.license = 'MIT'
s.date = Time.now.strftime('%Y-%m-%d')
s.files = Concurrent::FILE_MAP.fetch :core
s.extra_rdoc_files = Dir['README*', 'LICENSE*', 'CHANGELOG*']
s.require_paths = ['lib']
s.description = <<-EOF
Modern concurrency tools including agents, futures, promises, thread pools, actors, supervisors, and more.
Inspired by Erlang, Clojure, Go, JavaScript, actors, and classic concurrency patterns.
EOF

if defined?(JRUBY_VERSION)
s.files += Dir['lib/**/*.jar']
s.files += Dir['lib/**/*.jar']
s.platform = 'java'
else
s.add_runtime_dependency 'ref', '~> 1.0', '>= 1.0.5'
Expand Down
6 changes: 6 additions & 0 deletions lib/concurrent-edge.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
require 'concurrent'

require 'concurrent/actor'
require 'concurrent/channel'


2 changes: 0 additions & 2 deletions lib/concurrent.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,7 @@

require 'concurrent/configuration'

require 'concurrent/actor'
require 'concurrent/atomics'
require 'concurrent/channels'
require 'concurrent/collections'
require 'concurrent/errors'
require 'concurrent/executors'
Expand Down
3 changes: 0 additions & 3 deletions lib/concurrent/actress.rb

This file was deleted.

6 changes: 6 additions & 0 deletions lib/concurrent/channel.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
require 'concurrent/channel/blocking_ring_buffer'
require 'concurrent/channel/buffered_channel'
require 'concurrent/channel/channel'
require 'concurrent/channel/ring_buffer'
require 'concurrent/channel/unbuffered_channel'
require 'concurrent/channel/waitable_list'
5 changes: 0 additions & 5 deletions lib/concurrent/channels.rb

This file was deleted.

2 changes: 0 additions & 2 deletions lib/concurrent/collections.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1 @@
require 'concurrent/collection/priority_queue'
require 'concurrent/collection/ring_buffer'
require 'concurrent/collection/blocking_ring_buffer'
24 changes: 24 additions & 0 deletions lib/concurrent/edge.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
module Concurrent

# A submodule for unstable, highly experimental features that are likely to
# change often and which may never become part of the core gem. Also for
# new, experimental version of abstractions already in the core gem.
#
# Most new features should start in this module, clearly indicating the
# experimental and unstable nature of the feature. Once a feature becomes
# more stable and is a candidate for inclusion in the core gem it should
# be moved up to the `Concurrent` module, where it would reside once merged
# into the core gem.
#
# The only exception to this is for features which *replace* features from
# the core gem in ways that are breaking and not backward compatible. These
# features should remain in this module until merged into the core gem. This
# will prevent namespace collisions.
#
# This file should *never* be used as a global `require` for all files within
# the edge gem. Because these features are experimental users should always
# explicitly require only what they need.
module Edge

end
end
16 changes: 16 additions & 0 deletions lib/concurrent/file_map.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
module Concurrent

git_files = `git ls-files`.split("\n")
all_lib_files = Dir['lib/concurrent/**/*.rb'] & git_files
edge_lib_files = Dir['lib/concurrent/actor.rb',
'lib/concurrent/actor/**/*.rb',
'lib/concurrent/channel.rb',
'lib/concurrent/channel/**/*.rb'] & git_files
core_lib_files = all_lib_files - edge_lib_files

FILE_MAP = {
core: core_lib_files + %w(lib/concurrent.rb lib/concurrent_ruby.rb),
edge: edge_lib_files + %w(lib/concurrent-edge.rb)
}
end

3 changes: 2 additions & 1 deletion lib/concurrent/version.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
module Concurrent
VERSION = '0.8.0'
VERSION = '0.8.0'
EDGE_VERSION = '0.1.0'
end
1 change: 1 addition & 0 deletions lib/concurrent_ruby.rb
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
warn "'[DEPRECATED] use `require 'concurrent'` instead of `require 'concurrent_ruby'`"
require 'concurrent'
2 changes: 2 additions & 0 deletions spec/spec_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@

$VERBOSE = nil # suppress our deprecation warnings
require 'concurrent'
require 'concurrent/actor'
require 'concurrent/channel'

logger = Logger.new($stderr)
logger.level = Logger::WARN
Expand Down