Skip to content

Commit b87f738

Browse files
author
Petr Chalupa
committed
Merge pull request #274 from pitr-ch/devel
Edge development
2 parents 7ca211a + 4272db4 commit b87f738

Some content is hidden

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

50 files changed

+1701
-310
lines changed

.gitignore

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,4 +35,3 @@ ext/**/*.bundle
3535
ext/**/*.so
3636
ext/**/*.jar
3737
pkg
38-
*.gem

.rspec

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,4 @@
11
--require spec_helper
2-
--format progress
2+
--color
3+
--backtrace
4+
--format documentation

Gemfile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
source 'https://rubygems.org'
22

33
gemspec name: 'concurrent-ruby'
4+
gemspec name: 'concurrent-ruby-edge'
45

56
group :development do
67
gem 'rake', '~> 10.4.2'

README.md

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -52,15 +52,13 @@ This library contains a variety of concurrency abstractions at high and low leve
5252

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

55-
* [Actor](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/Actor.html): Implements the Actor Model, where concurrent actors exchange messages.
5655
* [Agent](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/Agent.html): A single atomic value that represents an identity.
5756
* [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.
5857
* [Future](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/Future.html): An asynchronous operation that produces a value.
5958
* [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.
6059
* [Promise](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/Promise.html): Similar to Futures, with more features.
6160
* [ScheduledTask](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/ScheduledTask.html): Like a Future scheduled for a specific future time.
6261
* [TimerTask](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/TimerTask.html): A Thread that periodically wakes up to perform work at regular intervals.
63-
* [Channel](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/Channel.html): Communicating Sequential Processes (CSP).
6462

6563
### Java-inspired ThreadPools and other executors
6664

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

91+
### Edge features
92+
93+
They are available in the `concurrent-ruby-edge` companion gem, install with `gem install concurrent-ruby-edge`.
94+
95+
These features are under active development and may change frequently. They are expected not to
96+
keep backward compatibility (there may also lack tests and documentation). Semantic versions will
97+
be obeyed though. Features developed in `concurrent-ruby-edge` are expected to move to `concurrent-ruby` when final.
98+
99+
* [Actor](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/Actor.html):
100+
Implements the Actor Model, where concurrent actors exchange messages.
101+
* [Channel](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/Channel.html):
102+
Communicating Sequential Processes (CSP).
103+
93104
## Usage
94105

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

106117
# groups
107118

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

@@ -127,6 +136,11 @@ require 'concurrent/promise' # Concurrent::Promise
127136
require 'concurrent/scheduled_task' # Concurrent::ScheduledTask
128137
require 'concurrent/timer_task' # Concurrent::TimerTask
129138
require 'concurrent/tvar' # Concurrent::TVar
139+
140+
# experimental - available in `concurrent-ruby-edge` companion gem
141+
142+
require 'concurrent/actor' # Concurrent::Actor and supporting code
143+
require 'concurrent/channel ' # Concurrent::Channel and supporting code
130144
```
131145

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

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

153167
```ruby
154168
gem install concurrent-ruby-ext

Rakefile

Lines changed: 28 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,27 @@
11
#!/usr/bin/env rake
22

3+
require 'concurrent/version'
34
require 'concurrent/native_extensions'
45

56
## load the two gemspec files
67
CORE_GEMSPEC = Gem::Specification.load('concurrent-ruby.gemspec')
78
EXT_GEMSPEC = Gem::Specification.load('concurrent-ruby-ext.gemspec')
9+
EDGE_GEMSPEC = Gem::Specification.load('concurrent-ruby-edge.gemspec')
810

911
## constants used for compile/build tasks
1012

1113
GEM_NAME = 'concurrent-ruby'
12-
EXTENSION_NAME = 'extension'
14+
EXT_NAME = 'extension'
15+
EDGE_NAME = 'edge'
1316
JAVA_EXT_NAME = 'concurrent_ruby_ext'
1417

1518
if Concurrent.on_jruby?
1619
CORE_GEM = "#{GEM_NAME}-#{Concurrent::VERSION}-java.gem"
1720
else
1821
CORE_GEM = "#{GEM_NAME}-#{Concurrent::VERSION}.gem"
19-
EXTENSION_GEM = "#{GEM_NAME}-ext-#{Concurrent::VERSION}.gem"
22+
EXT_GEM = "#{GEM_NAME}-ext-#{Concurrent::VERSION}.gem"
2023
NATIVE_GEM = "#{GEM_NAME}-ext-#{Concurrent::VERSION}-#{Gem::Platform.new(RUBY_PLATFORM)}.gem"
24+
EDGE_GEM = "#{GEM_NAME}-edge-#{Concurrent::EDGE_VERSION}.gem"
2125
end
2226

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

52-
Rake::ExtensionTask.new(EXTENSION_NAME, EXT_GEMSPEC) do |ext|
56+
Rake::ExtensionTask.new(EXT_NAME, EXT_GEMSPEC) do |ext|
5357
ext.ext_dir = 'ext/concurrent'
5458
ext.lib_dir = 'lib/concurrent'
5559
ext.source_pattern = '*.{c,h}'
@@ -63,9 +67,9 @@ elsif Concurrent.allow_c_extensions?
6367
'x64-mingw32' => 'x86_64-w64-mingw32'
6468
}
6569
platforms.each do |platform, prefix|
66-
task "copy:#{EXTENSION_NAME}:#{platform}:#{ruby_version}" do |t|
70+
task "copy:#{EXT_NAME}:#{platform}:#{ruby_version}" do |t|
6771
%w[lib tmp/#{platform}/stage/lib].each do |dir|
68-
so_file = "#{dir}/#{ruby_version[/^\d+\.\d+/]}/#{EXTENSION_NAME}.so"
72+
so_file = "#{dir}/#{ruby_version[/^\d+\.\d+/]}/#{EXT_NAME}.so"
6973
if File.exists?(so_file)
7074
sh "#{prefix}-strip -S #{so_file}"
7175
end
@@ -94,7 +98,11 @@ end
9498

9599
namespace :build do
96100

97-
build_deps = [:clean]
101+
task :mkdir_pkg do
102+
mkdir_p 'pkg'
103+
end
104+
105+
build_deps = [:clean, 'build:mkdir_pkg']
98106
build_deps << :compile if Concurrent.on_jruby?
99107

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

106114
unless Concurrent.on_jruby?
107-
desc "Build #{EXTENSION_GEM} into the pkg directory"
108-
task :ext => [:clean] do
115+
116+
desc "Build #{EDGE_GEM} into the pkg directory"
117+
task :edge => 'build:mkdir_pkg' do
118+
sh "gem build #{EDGE_GEMSPEC.name}.gemspec"
119+
sh 'mv *.gem pkg/'
120+
end
121+
122+
desc "Build #{EXT_GEM} into the pkg directory"
123+
task :ext => build_deps do
109124
sh "gem build #{EXT_GEMSPEC.name}.gemspec"
110125
sh 'mv *.gem pkg/'
111126
end
112127
end
113128

114129
if Concurrent.allow_c_extensions?
115130
desc "Build #{NATIVE_GEM} into the pkg directory"
116-
task :native do
117-
sh "gem compile pkg/#{EXTENSION_GEM}"
131+
task :native => 'build:mkdir_pkg' do
132+
sh "gem compile pkg/#{EXT_GEM}"
118133
sh 'mv *.gem pkg/'
119134
end
120135
end
@@ -124,8 +139,8 @@ if Concurrent.on_jruby?
124139
desc 'Build JRuby-specific core gem (alias for `build:core`)'
125140
task :build => ['build:core']
126141
else
127-
desc 'Build core and extension gems'
128-
task :build => ['build:core', 'build:ext']
142+
desc 'Build core, extension, and edge gems'
143+
task :build => ['build:core', 'build:ext', 'build:edge']
129144
end
130145

131146
## the RSpec task that compiles extensions when available
@@ -134,9 +149,7 @@ begin
134149
require 'rspec'
135150
require 'rspec/core/rake_task'
136151

137-
RSpec::Core::RakeTask.new(:spec) do |t|
138-
t.rspec_opts = '--color --backtrace --format documentation'
139-
end
152+
RSpec::Core::RakeTask.new(:spec)
140153

141154
task :default => [:clean, :compile, :spec]
142155
rescue LoadError

concurrent-ruby-edge.gemspec

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
$:.push File.join(File.dirname(__FILE__), 'lib')
2+
3+
require 'concurrent/version'
4+
require 'concurrent/file_map'
5+
6+
Gem::Specification.new do |s|
7+
git_files = `git ls-files`.split("\n")
8+
9+
s.name = 'concurrent-ruby-edge'
10+
s.version = Concurrent::EDGE_VERSION
11+
s.platform = Gem::Platform::RUBY
12+
s.authors = ["Jerry D'Antonio", 'The Ruby Concurrency Team']
13+
14+
s.homepage = 'http://www.concurrent-ruby.com'
15+
s.summary = 'Edge features and additions to the concurrent-ruby gem.'
16+
s.license = 'MIT'
17+
s.date = Time.now.strftime('%Y-%m-%d')
18+
s.files = Concurrent::FILE_MAP.fetch :edge
19+
s.extra_rdoc_files = Dir['README*', 'LICENSE*']
20+
s.require_paths = ['lib']
21+
s.description = <<-TXT
22+
These features are under active development and may change frequently. They are expected not to
23+
keep backward compatibility (there may also lack tests and documentation). Semantic versions will
24+
be obeyed though. Features developed in `concurrent-ruby-edge` are expected to move to `concurrent-ruby` when final.
25+
Please see http://concurrent-ruby.com for more information.
26+
TXT
27+
28+
s.required_ruby_version = '>= 1.9.3'
29+
30+
s.add_runtime_dependency 'concurrent-ruby', "~> #{Concurrent::VERSION}"
31+
end

concurrent-ruby.gemspec

Lines changed: 17 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,30 @@
11
$:.push File.join(File.dirname(__FILE__), 'lib')
22

33
require 'concurrent/version'
4+
require 'concurrent/file_map'
45

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

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

2526
if defined?(JRUBY_VERSION)
26-
s.files += Dir['lib/**/*.jar']
27+
s.files += Dir['lib/**/*.jar']
2728
s.platform = 'java'
2829
else
2930
s.add_runtime_dependency 'ref', '~> 1.0', '>= 1.0.5'

doc/future-promise.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
# Futures and Promises
2+
3+
New implementation added in version 0.8 differs from previous versions and has little in common.
4+
{Future} represents a value which will become {#completed?} in future, it'll contain {#value} if {#success?} or a {#reason} if {#failed?}. It cannot be directly completed, there are implementations of abstract {Promise} class for that, so {Promise}'s only purpose is to complete a given {Future} object. They are always constructed as a Pair even in chaining methods like {#then}, {#rescue}, {#then_delay}, etc.
5+
6+
There is few {Promise} implementations:
7+
8+
- OuterPromise - only Promise used by users, can be completed by outer code. Constructed with {Concurrent::Next.promise} helper method.
9+
- Immediate - internal implementation of Promise used to represent immediate evaluation of a block. Constructed with {Concurrent::Next.future} helper method.
10+
- Delay - internal implementation of Promise used to represent delayed evaluation of a block. Constructed with {Concurrent::Next.delay} helper method.
11+
- ConnectedPromise - used internally to support {Future#with_default_executor}
12+

lib/concurrent-edge.rb

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
require 'concurrent'
2+
3+
require 'concurrent/actor'
4+
require 'concurrent/channel'
5+
require 'concurrent/edge/future'
6+
7+

lib/concurrent.rb

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,7 @@
55

66
require 'concurrent/configuration'
77

8-
require 'concurrent/actor'
98
require 'concurrent/atomics'
10-
require 'concurrent/channels'
119
require 'concurrent/collections'
1210
require 'concurrent/errors'
1311
require 'concurrent/executors'

0 commit comments

Comments
 (0)