concurrent-ruby-ext 0.1.0.pre1-x64-mingw32
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +15 -0
- data/CHANGELOG.md +149 -0
- data/LICENSE.txt +21 -0
- data/README.md +200 -0
- data/ext/concurrent_ruby_ext/atomic_boolean.c +48 -0
- data/ext/concurrent_ruby_ext/atomic_boolean.h +16 -0
- data/ext/concurrent_ruby_ext/atomic_fixnum.c +50 -0
- data/ext/concurrent_ruby_ext/atomic_fixnum.h +13 -0
- data/ext/concurrent_ruby_ext/atomic_reference.c +91 -0
- data/ext/concurrent_ruby_ext/atomic_reference.h +20 -0
- data/ext/concurrent_ruby_ext/extconf.rb +58 -0
- data/ext/concurrent_ruby_ext/rb_concurrent.c +57 -0
- data/ext/concurrent_ruby_ext/ruby_193_compatible.h +28 -0
- data/lib/2.0/concurrent_ruby_ext.so +0 -0
- data/lib/concurrent/atomic_reference/concurrent_update_error.rb +8 -0
- data/lib/concurrent/atomic_reference/direct_update.rb +50 -0
- data/lib/concurrent/atomic_reference/numeric_cas_wrapper.rb +25 -0
- metadata +78 -0
checksums.yaml
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
---
|
2
|
+
!binary "U0hBMQ==":
|
3
|
+
metadata.gz: !binary |-
|
4
|
+
ZTcyY2NmM2U4ZmY1MzljZjlkYmMyZDViNzMwMTM3NTc0OTk4MDNmOQ==
|
5
|
+
data.tar.gz: !binary |-
|
6
|
+
MjU4NjA4OGI0NmQ0ZGQzZWI2OTIzNWVkOWZkYWZiYWIwMDc0ZjBjYQ==
|
7
|
+
SHA512:
|
8
|
+
metadata.gz: !binary |-
|
9
|
+
MWVjMTkyNjVkZmNmMTM2MmY3OTY5YWVhNjNiODBmM2FhMmZiMjJiMTI3YzFj
|
10
|
+
OTZiZmE2MGMwYWU4OWY5NmUwZWZkZmVkZmM0YTMxYzY2OGQ0YTdlY2NkNzhm
|
11
|
+
Mjg5ZjQ5NzQwYjJiMWQ0ZjFlZWYzNTNhNzNlNzFkZWZjM2MzMGY=
|
12
|
+
data.tar.gz: !binary |-
|
13
|
+
ZWRjNDc0OWU2NWNhOWU5OWZlMmRlZWJjNDM2OTE1MmRjOWYyMWQ0NDM3YjY2
|
14
|
+
NTUxOTBkMDM2NGQzNTczYWE1MDM4N2U1YjM4MDBkNjc5N2ZkYzgwZDkwZDZh
|
15
|
+
NjMwY2M3YjJlZjAzMTIzMDQ3ZTAxZWIxOWY1MjNhMzVkNDkyNjU=
|
data/CHANGELOG.md
ADDED
@@ -0,0 +1,149 @@
|
|
1
|
+
### Next Release v0.7.2 (TBD)
|
2
|
+
|
3
|
+
* New `Promise.all?` and `Promise.any?` class methods
|
4
|
+
* Renamed `:overflow_policy` on thread pools to `:fallback_policy`
|
5
|
+
* Thread pools still accept the `:overflow_policy` option but display a warning
|
6
|
+
* Thread pools now implement `fallback_policy` behavior when not running (rather than universally rejecting tasks)
|
7
|
+
* Fixed minor `set_deref_options` constructor bug in `Promise` class
|
8
|
+
* Numerous non-functional updates to clear warning when running in debug mode
|
9
|
+
* Fixed more intermittently failing tests
|
10
|
+
* Tests now run on new Travis build environment
|
11
|
+
|
12
|
+
## Current Release v0.7.1 (4 December 2014)
|
13
|
+
|
14
|
+
Please see the [roadmap](https://github.com/ruby-concurrency/concurrent-ruby/issues/142) for more information on the next planned release.
|
15
|
+
|
16
|
+
* Added `flat_map` method to `Promise`
|
17
|
+
* Added `zip` method to `Promise`
|
18
|
+
* Fixed bug with logging in `Actor`
|
19
|
+
* Improvements to `Promise` tests
|
20
|
+
* Removed actor-experimental warning
|
21
|
+
* Added an `IndirectImmediateExecutor` class
|
22
|
+
* Allow disabling auto termination of global executors
|
23
|
+
* Fix thread leaking in `ThreadLocalVar` (uses `Ref` gem on non-JRuby systems)
|
24
|
+
* Fix thread leaking when pruning pure-Ruby thread pools
|
25
|
+
* Prevent `Actor` from using an `ImmediateExecutor` (causes deadlock)
|
26
|
+
* Added missing synchronizations to `TimerSet`
|
27
|
+
* Fixed bug with return value of `Concurrent::Actor::Utils::Pool#ask`
|
28
|
+
* Fixed timing bug in `TimerTask`
|
29
|
+
* Fixed bug when creating a `JavaThreadPoolExecutor` with minimum pool size of zero
|
30
|
+
* Removed confusing warning when not using native extenstions
|
31
|
+
* Improved documentation
|
32
|
+
|
33
|
+
### Release v0.7.0 (13 August 2014)
|
34
|
+
|
35
|
+
* Merge the [atomic](https://github.com/ruby-concurrency/atomic) gem
|
36
|
+
- Pure Ruby `MutexAtomic` atomic reference class
|
37
|
+
- Platform native atomic reference classes `CAtomic`, `JavaAtomic`, and `RbxAtomic`
|
38
|
+
- Automated [build process](https://github.com/ruby-concurrency/rake-compiler-dev-box)
|
39
|
+
- Fat binary releases for [multiple platforms](https://rubygems.org/gems/concurrent-ruby/versions) including Windows (32/64), Linux (32/64), OS X (64-bit), Solaris (64-bit), and JRuby
|
40
|
+
* C native `CAtomicBoolean`
|
41
|
+
* C native `CAtomicFixnum`
|
42
|
+
* Refactored intermittently failing tests
|
43
|
+
* Added `dataflow!` and `dataflow_with!` methods to match `Future#value!` method
|
44
|
+
* Better handling of timeout in `Agent`
|
45
|
+
* Actor Improvements
|
46
|
+
- Fine-grained implementation using chain of behaviors. Each behavior is responsible for single aspect like: `Termination`, `Pausing`, `Linking`, `Supervising`, etc. Users can create custom Actors easily based on their needs.
|
47
|
+
- Supervision was added. `RestartingContext` will pause on error waiting on its supervisor to decide what to do next ( options are `:terminate!`, `:resume!`, `:reset!`, `:restart!`). Supervising behavior also supports strategies `:one_for_one` and `:one_for_all`.
|
48
|
+
- Linking was added to be able to monitor actor's events like: `:terminated`, `:paused`, `:restarted`, etc.
|
49
|
+
- Dead letter routing added. Rejected envelopes are collected in a configurable actor (default: `Concurrent::Actor.root.ask!(:dead_letter_routing)`)
|
50
|
+
- Old `Actor` class removed and replaced by new implementation previously called `Actress`. `Actress` was kept as an alias for `Actor` to keep compatibility.
|
51
|
+
- `Utils::Broadcast` actor which allows Publish–subscribe pattern.
|
52
|
+
* More executors for managing serialized operations
|
53
|
+
- `SerializedExecution` mixin module
|
54
|
+
- `SerializedExecutionDelegator` for serializing *any* executor
|
55
|
+
* Updated `Async` with serialized execution
|
56
|
+
* Updated `ImmediateExecutor` and `PerThreadExecutor` with full executor service lifecycle
|
57
|
+
* Added a `Delay` to root `Actress` initialization
|
58
|
+
* Minor bug fixes to thread pools
|
59
|
+
* Refactored many intermittently failing specs
|
60
|
+
* Removed Java interop warning `executor.rb:148 warning: ambiguous Java methods found, using submit(java.lang.Runnable)`
|
61
|
+
* Fixed minor bug in `RubyCachedThreadPool` overflow policy
|
62
|
+
* Updated tests to use [RSpec 3.0](http://myronmars.to/n/dev-blog/2014/05/notable-changes-in-rspec-3)
|
63
|
+
* Removed deprecated `Actor` class
|
64
|
+
* Better support for Rubinius
|
65
|
+
|
66
|
+
### Release v0.6.1 (14 June 2014)
|
67
|
+
|
68
|
+
* Many improvements to `Concurrent::Actress`
|
69
|
+
* Bug fixes to `Concurrent::RubyThreadPoolExecutor`
|
70
|
+
* Fixed several brittle tests
|
71
|
+
* Moved documentation to http://ruby-concurrency.github.io/concurrent-ruby/frames.html
|
72
|
+
|
73
|
+
### Release v0.6.0 (25 May 2014)
|
74
|
+
|
75
|
+
* Added `Concurrent::Observable` to encapsulate our thread safe observer sets
|
76
|
+
* Improvements to new `Channel`
|
77
|
+
* Major improvements to `CachedThreadPool` and `FixedThreadPool`
|
78
|
+
* Added `SingleThreadExecutor`
|
79
|
+
* Added `Current::timer` function
|
80
|
+
* Added `TimerSet` executor
|
81
|
+
* Added `AtomicBoolean`
|
82
|
+
* `ScheduledTask` refactoring
|
83
|
+
* Pure Ruby and JRuby-optimized `PriorityQueue` classes
|
84
|
+
* Updated `Agent` behavior to more closely match Clojure
|
85
|
+
* Observer sets support block callbacks to the `add_observer` method
|
86
|
+
* New algorithm for thread creation in `RubyThreadPoolExecutor`
|
87
|
+
* Minor API updates to `Event`
|
88
|
+
* Rewritten `TimerTask` now an `Executor` instead of a `Runnable`
|
89
|
+
* Fixed many brittle specs
|
90
|
+
* Renamed `FixedThreadPool` and `CachedThreadPool` to `RubyFixedThreadPool` and `RubyCachedThreadPool`
|
91
|
+
* Created JRuby optimized `JavaFixedThreadPool` and `JavaCachedThreadPool`
|
92
|
+
* Consolidated fixed thread pool tests into `spec/concurrent/fixed_thread_pool_shared.rb` and `spec/concurrent/cached_thread_pool_shared.rb`
|
93
|
+
* `FixedThreadPool` now subclasses `RubyFixedThreadPool` or `JavaFixedThreadPool` as appropriate
|
94
|
+
* `CachedThreadPool` now subclasses `RubyCachedThreadPool` or `JavaCachedThreadPool` as appropriate
|
95
|
+
* New `Delay` class
|
96
|
+
* `Concurrent::processor_count` helper function
|
97
|
+
* New `Async` module
|
98
|
+
* Renamed `NullThreadPool` to `PerThreadExecutor`
|
99
|
+
* Deprecated `Channel` (we are planning a new implementation based on [Go](http://golangtutorials.blogspot.com/2011/06/channels-in-go.html))
|
100
|
+
* Added gem-level [configuration](http://robots.thoughtbot.com/mygem-configure-block)
|
101
|
+
* Deprecated `$GLOBAL_THREAD_POOL` in lieu of gem-level configuration
|
102
|
+
* Removed support for Ruby [1.9.2](https://www.ruby-lang.org/en/news/2013/12/17/maintenance-of-1-8-7-and-1-9-2/)
|
103
|
+
* New `RubyThreadPoolExecutor` and `JavaThreadPoolExecutor` classes
|
104
|
+
* All thread pools now extend the appropriate thread pool executor classes
|
105
|
+
* All thread pools now support `:overflow_policy` (based on Java's [reject policies](http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ThreadPoolExecutor.html))
|
106
|
+
* Deprecated `UsesGlobalThreadPool` in lieu of explicit `:executor` option (dependency injection) on `Future`, `Promise`, and `Agent`
|
107
|
+
* Added `Concurrent::dataflow_with(executor, *inputs)` method to support executor dependency injection for dataflow
|
108
|
+
* Software transactional memory with `TVar` and `Concurrent::atomically`
|
109
|
+
* First implementation of [new, high-performance](https://github.com/ruby-concurrency/concurrent-ruby/pull/49) `Channel`
|
110
|
+
* `Actor` is deprecated in favor of new experimental actor implementation [#73](https://github.com/ruby-concurrency/concurrent-ruby/pull/73). To avoid namespace collision it is living in `Actress` namespace until `Actor` is removed in next release.
|
111
|
+
|
112
|
+
### Release v0.5.0
|
113
|
+
|
114
|
+
This is the most significant release of this gem since its inception. This release includes many improvements and optimizations. It also includes several bug fixes. The major areas of focus for this release were:
|
115
|
+
|
116
|
+
* Stability improvements on Ruby versions with thread-level parallelism ([JRuby](http://jruby.org/) and [Rubinius](http://rubini.us/))
|
117
|
+
* Creation of new low-level concurrency abstractions
|
118
|
+
* Internal refactoring to use the new low-level abstractions
|
119
|
+
|
120
|
+
Most of these updates had no effect on the gem API. There are a few notable exceptions which were unavoidable. Please read the [release notes](API-Updates-in-v0.5.0) for more information.
|
121
|
+
|
122
|
+
Specific changes include:
|
123
|
+
|
124
|
+
* New class `IVar`
|
125
|
+
* New class `MVar`
|
126
|
+
* New class `ThreadLocalVar`
|
127
|
+
* New class `AtomicFixnum`
|
128
|
+
* New class method `dataflow`
|
129
|
+
* New class `Condition`
|
130
|
+
* New class `CountDownLatch`
|
131
|
+
* New class `DependencyCounter`
|
132
|
+
* New class `SafeTaskExecutor`
|
133
|
+
* New class `CopyOnNotifyObserverSet`
|
134
|
+
* New class `CopyOnWriteObserverSet`
|
135
|
+
* `Future` updated with `execute` API
|
136
|
+
* `ScheduledTask` updated with `execute` API
|
137
|
+
* New `Promise` API
|
138
|
+
* `Future` now extends `IVar`
|
139
|
+
* `Postable#post?` now returns an `IVar`
|
140
|
+
* Thread safety fixes to `Dereferenceable`
|
141
|
+
* Thread safety fixes to `Obligation`
|
142
|
+
* Thread safety fixes to `Supervisor`
|
143
|
+
* Thread safety fixes to `Event`
|
144
|
+
* Various other thread safety (race condition) fixes
|
145
|
+
* Refactored brittle tests
|
146
|
+
* Implemented pending tests
|
147
|
+
* Added JRuby and Rubinius as Travis CI build targets
|
148
|
+
* Added [CodeClimate](https://codeclimate.com/) code review
|
149
|
+
* Improved YARD documentation
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
Copyright (c) Jerry D'Antonio -- released under the MIT license.
|
2
|
+
|
3
|
+
http://www.opensource.org/licenses/mit-license.php
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,200 @@
|
|
1
|
+
# Concurrent Ruby
|
2
|
+
[![Gem Version](https://badge.fury.io/rb/concurrent-ruby.svg)](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://img.shields.io/coveralls/ruby-concurrency/concurrent-ruby/master.svg)](https://coveralls.io/r/ruby-concurrency/concurrent-ruby) [![Code Climate](https://codeclimate.com/github/ruby-concurrency/concurrent-ruby.svg)](https://codeclimate.com/github/ruby-concurrency/concurrent-ruby) [![Inline docs](http://inch-ci.org/github/ruby-concurrency/concurrent-ruby.svg)](http://inch-ci.org/github/ruby-concurrency/concurrent-ruby) [![Dependency Status](https://gemnasium.com/ruby-concurrency/concurrent-ruby.svg)](https://gemnasium.com/ruby-concurrency/concurrent-ruby) [![License](https://img.shields.io/badge/license-MIT-green.svg)](http://opensource.org/licenses/MIT) [![Gitter chat](http://img.shields.io/badge/gitter-join%20chat%20%E2%86%92-brightgreen.svg)](https://gitter.im/ruby-concurrency/concurrent-ruby)
|
3
|
+
|
4
|
+
<table>
|
5
|
+
<tr>
|
6
|
+
<td align="left" valign="top">
|
7
|
+
<p>
|
8
|
+
Modern concurrency tools for Ruby. Inspired by
|
9
|
+
<a href="http://www.erlang.org/doc/reference_manual/processes.html">Erlang</a>,
|
10
|
+
<a href="http://clojure.org/concurrent_programming">Clojure</a>,
|
11
|
+
<a href="http://akka.io/">Scala</a>,
|
12
|
+
<a href="http://www.haskell.org/haskellwiki/Applications_and_libraries/Concurrency_and_parallelism#Concurrent_Haskell">Haskell</a>,
|
13
|
+
<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>,
|
14
|
+
<a href="http://msdn.microsoft.com/en-us/library/vstudio/hh191443.aspx">C#</a>,
|
15
|
+
<a href="http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/package-summary.html">Java</a>,
|
16
|
+
and classic concurrency patterns.
|
17
|
+
</p>
|
18
|
+
<p>
|
19
|
+
The design goals of this gem are:
|
20
|
+
<ul>
|
21
|
+
<li>Be an 'unopinionated' toolbox that provides useful utilities without debating which is better or why</li>
|
22
|
+
<li>Remain free of external gem dependencies</li>
|
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/ruby-concurrency/concurrent-ruby/master/doc/logo/concurrent-ruby-logo-300x300.png"/>
|
34
|
+
</td>
|
35
|
+
</tr>
|
36
|
+
</table>
|
37
|
+
|
38
|
+
### Supported Ruby versions
|
39
|
+
|
40
|
+
MRI 1.9.3, 2.0, 2.1, JRuby (1.9 mode), and Rubinius 2.x are supported.
|
41
|
+
This gem should be fully compatible with any interpreter that is compliant with Ruby 1.9.3 or newer.
|
42
|
+
|
43
|
+
## Features & Documentation
|
44
|
+
|
45
|
+
We have a roadmap guiding our work toward the [v1.0.0 release](https://github.com/ruby-concurrency/concurrent-ruby/wiki/v1.0-Roadmap).
|
46
|
+
|
47
|
+
The primary site for documentation is the automatically generated [API documentation](http://ruby-concurrency.github.io/concurrent-ruby/frames.html)
|
48
|
+
|
49
|
+
We also have a [mailing list](http://groups.google.com/group/concurrent-ruby).
|
50
|
+
|
51
|
+
This library contains a variety of concurrency abstractions at high and low levels. One of the high-level abstractions is likely to meet most common needs.
|
52
|
+
|
53
|
+
### High-level, general-purpose asynchronous concurrency abstractions
|
54
|
+
|
55
|
+
* [Actor](./doc/actor/main.md): Implements the Actor Model, where concurrent actors exchange messages.
|
56
|
+
* [Agent](./doc/agent.md): A single atomic value that represents an identity.
|
57
|
+
* [Async](./doc/async.md): A mixin module that provides simple asynchronous behavior to any standard class/object or object.
|
58
|
+
* [Future](./doc/future.md): An asynchronous operation that produces a value.
|
59
|
+
* [Dataflow](./doc/dataflow.md): Built on Futures, Dataflow allows you to create a task that will be scheduled when all of its data dependencies are available.
|
60
|
+
* [Promise](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/Promise.html): Similar to Futures, with more features.
|
61
|
+
* [ScheduledTask](./doc/scheduled_task.md): Like a Future scheduled for a specific future time.
|
62
|
+
* [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).
|
64
|
+
|
65
|
+
### Java-inspired ThreadPools and other executors
|
66
|
+
|
67
|
+
* See [ThreadPool](./doc/thread_pools.md) overview, which also contains a list of other Executors available.
|
68
|
+
|
69
|
+
### Thread-safe Observers
|
70
|
+
|
71
|
+
* [Concurrent::Observable](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/Observable.html) mixin module
|
72
|
+
* [CopyOnNotifyObserverSet](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/CopyOnNotifyObserverSet.html)
|
73
|
+
* [CopyOnWriteObserverSet](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/CopyOnWriteObserverSet.html)
|
74
|
+
|
75
|
+
### Thread synchronization classes and algorithms
|
76
|
+
Lower-level abstractions mainly used as building blocks.
|
77
|
+
|
78
|
+
* [condition](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/Condition.html)
|
79
|
+
* [countdown latch](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/CountDownLatch.html)
|
80
|
+
* [cyclic barrier](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/CyclicBarrier.html)
|
81
|
+
* [event](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/Event.html)
|
82
|
+
* [exchanger](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/Exchanger.html)
|
83
|
+
* [timeout](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent.html#timeout-class_method)
|
84
|
+
* [timer](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent.html#timer-class_method)
|
85
|
+
|
86
|
+
### Thread-safe variables
|
87
|
+
Lower-level abstractions mainly used as building blocks.
|
88
|
+
|
89
|
+
* [AtomicBoolean](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/AtomicBoolean.html)
|
90
|
+
* [AtomicFixnum](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/AtomicFixnum.html)
|
91
|
+
* AtomicReference (no docs currently available, check source)
|
92
|
+
* [I-Structures](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/IVar.html) (IVar)
|
93
|
+
* [M-Structures](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/MVar.html) (MVar)
|
94
|
+
* [thread-local variables](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/ThreadLocalVar.html)
|
95
|
+
* [software transactional memory](./doc/tvar.md) (TVar)
|
96
|
+
|
97
|
+
## Usage
|
98
|
+
|
99
|
+
All abstractions within this gem can be loaded simply by requiring it:
|
100
|
+
|
101
|
+
```ruby
|
102
|
+
require 'concurrent'
|
103
|
+
```
|
104
|
+
|
105
|
+
To reduce the amount of code loaded at runtime, subsets of this gem can be required:
|
106
|
+
|
107
|
+
```ruby
|
108
|
+
require 'concurrent' # everything
|
109
|
+
|
110
|
+
# groups
|
111
|
+
|
112
|
+
require 'concurrent/actor' # Concurrent::Actor and supporting code
|
113
|
+
require 'concurrent/atomics' # atomic and thread synchronization classes
|
114
|
+
require 'concurrent/channels' # Concurrent::Channel and supporting code
|
115
|
+
require 'concurrent/executors' # Thread pools and other executors
|
116
|
+
require 'concurrent/utilities' # utility methods such as processor count and timers
|
117
|
+
|
118
|
+
# individual abstractions
|
119
|
+
|
120
|
+
require 'concurrent/agent' # Concurrent::Agent
|
121
|
+
require 'concurrent/async' # Concurrent::Async
|
122
|
+
require 'concurrent/atomic' # Concurrent::Atomic (formerly the `atomic` gem)
|
123
|
+
require 'concurrent/dataflow' # Concurrent::dataflow
|
124
|
+
require 'concurrent/delay' # Concurrent::Delay
|
125
|
+
require 'concurrent/exchanger' # Concurrent::Exchanger
|
126
|
+
require 'concurrent/future' # Concurrent::Future
|
127
|
+
require 'concurrent/ivar' # Concurrent::IVar
|
128
|
+
require 'concurrent/mvar' # Concurrent::MVar
|
129
|
+
require 'concurrent/promise' # Concurrent::Promise
|
130
|
+
require 'concurrent/scheduled_task' # Concurrent::ScheduledTask
|
131
|
+
require 'concurrent/timer_task' # Concurrent::TimerTask
|
132
|
+
require 'concurrent/tvar' # Concurrent::TVar
|
133
|
+
```
|
134
|
+
|
135
|
+
## Installation
|
136
|
+
|
137
|
+
```shell
|
138
|
+
gem install concurrent-ruby
|
139
|
+
```
|
140
|
+
|
141
|
+
or add the following line to Gemfile:
|
142
|
+
|
143
|
+
```ruby
|
144
|
+
gem 'concurrent-ruby'
|
145
|
+
```
|
146
|
+
|
147
|
+
and run `bundle install` from your shell.
|
148
|
+
|
149
|
+
### C Extensions for MRI
|
150
|
+
|
151
|
+
Potential performance improvements may be achieved under MRI by installing optional C extensions.
|
152
|
+
To minimize installation errors the C extensions are available in the `concurrent-ruby-ext` extension
|
153
|
+
gem. The extension gem lists `concurrent-ruby` as a dependency so it is not necessary to install both.
|
154
|
+
Simply install the extension gen:
|
155
|
+
|
156
|
+
```shell
|
157
|
+
gem install concurrent-ruby-ext
|
158
|
+
```
|
159
|
+
|
160
|
+
or add the following line to Gemfile:
|
161
|
+
|
162
|
+
```ruby
|
163
|
+
gem 'concurrent-ruby-ext'
|
164
|
+
```
|
165
|
+
|
166
|
+
and run `bundle install` from your shell.
|
167
|
+
|
168
|
+
In code it is only necessary to
|
169
|
+
|
170
|
+
```shell
|
171
|
+
require 'concurrent'
|
172
|
+
```
|
173
|
+
|
174
|
+
The `concurrent-ruby` gem will automatically detect the presence of the `concurrent-ruby-ext` gem
|
175
|
+
and load the appropriate C extensions.
|
176
|
+
|
177
|
+
## Maintainers
|
178
|
+
|
179
|
+
* [Jerry D'Antonio](https://github.com/jdantonio)
|
180
|
+
* [Michele Della Torre](https://github.com/mighe)
|
181
|
+
* [Chris Seaton](https://github.com/chrisseaton)
|
182
|
+
* [Lucas Allan](https://github.com/lucasallan)
|
183
|
+
* [Petr Chalupa](https://github.com/pitr-ch)
|
184
|
+
* [Paweł Obrok](https://github.com/obrok)
|
185
|
+
|
186
|
+
### Contributing
|
187
|
+
|
188
|
+
1. Fork it
|
189
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
190
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
191
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
192
|
+
5. Create new Pull Request
|
193
|
+
|
194
|
+
## License and Copyright
|
195
|
+
|
196
|
+
*Concurrent Ruby* is free software released under the [MIT License](http://www.opensource.org/licenses/MIT).
|
197
|
+
|
198
|
+
The *Concurrent Ruby* [logo](https://github.com/ruby-concurrency/concurrent-ruby/wiki/Logo)
|
199
|
+
was designed by [David Jones](https://twitter.com/zombyboy).
|
200
|
+
It is Copyright © 2014 [Jerry D'Antonio](https://twitter.com/jerrydantonio). All Rights Reserved.
|
@@ -0,0 +1,48 @@
|
|
1
|
+
#include <ruby.h>
|
2
|
+
|
3
|
+
#include "atomic_boolean.h"
|
4
|
+
#include "atomic_reference.h"
|
5
|
+
#include "ruby_193_compatible.h"
|
6
|
+
|
7
|
+
void atomic_boolean_mark(void *value) {
|
8
|
+
rb_gc_mark_maybe((VALUE) value);
|
9
|
+
}
|
10
|
+
|
11
|
+
VALUE atomic_boolean_allocate(VALUE klass) {
|
12
|
+
return rb_data_object_alloc(klass, (void *) Qfalse, atomic_boolean_mark, NULL);
|
13
|
+
}
|
14
|
+
|
15
|
+
VALUE method_atomic_boolean_initialize(int argc, VALUE* argv, VALUE self) {
|
16
|
+
VALUE value = Qfalse;
|
17
|
+
rb_check_arity(argc, 0, 1);
|
18
|
+
if (argc == 1) value = TRUTHY(argv[0]);
|
19
|
+
DATA_PTR(self) = (void *) value;
|
20
|
+
return(self);
|
21
|
+
}
|
22
|
+
|
23
|
+
VALUE method_atomic_boolean_value(VALUE self) {
|
24
|
+
return (VALUE) DATA_PTR(self);
|
25
|
+
}
|
26
|
+
|
27
|
+
VALUE method_atomic_boolean_value_set(VALUE self, VALUE value) {
|
28
|
+
VALUE new_value = TRUTHY(value);
|
29
|
+
DATA_PTR(self) = (void *) new_value;
|
30
|
+
return(new_value);
|
31
|
+
}
|
32
|
+
|
33
|
+
VALUE method_atomic_boolean_true_question(VALUE self) {
|
34
|
+
return(method_atomic_boolean_value(self));
|
35
|
+
}
|
36
|
+
|
37
|
+
VALUE method_atomic_boolean_false_question(VALUE self) {
|
38
|
+
VALUE current = method_atomic_boolean_value(self);
|
39
|
+
return(current == Qfalse ? Qtrue : Qfalse);
|
40
|
+
}
|
41
|
+
|
42
|
+
VALUE method_atomic_boolean_make_true(VALUE self) {
|
43
|
+
return(ir_compare_and_set(self, Qfalse, Qtrue));
|
44
|
+
}
|
45
|
+
|
46
|
+
VALUE method_atomic_boolean_make_false(VALUE self) {
|
47
|
+
return(ir_compare_and_set(self, Qtrue, Qfalse));
|
48
|
+
}
|
@@ -0,0 +1,16 @@
|
|
1
|
+
#ifndef __ATOMIC_BOOLEAN_H__
|
2
|
+
#define __ATOMIC_BOOLEAN_H__
|
3
|
+
|
4
|
+
#define TRUTHY(value)(value == Qfalse || value == Qnil ? Qfalse : Qtrue)
|
5
|
+
|
6
|
+
void atomic_boolean_mark(void*);
|
7
|
+
VALUE atomic_boolean_allocate(VALUE);
|
8
|
+
VALUE method_atomic_boolean_initialize(int, VALUE*, VALUE);
|
9
|
+
VALUE method_atomic_boolean_value(VALUE);
|
10
|
+
VALUE method_atomic_boolean_value_set(VALUE, VALUE);
|
11
|
+
VALUE method_atomic_boolean_true_question(VALUE);
|
12
|
+
VALUE method_atomic_boolean_false_question(VALUE);
|
13
|
+
VALUE method_atomic_boolean_make_true(VALUE);
|
14
|
+
VALUE method_atomic_boolean_make_false(VALUE);
|
15
|
+
|
16
|
+
#endif
|
@@ -0,0 +1,50 @@
|
|
1
|
+
#include <ruby.h>
|
2
|
+
|
3
|
+
#include "atomic_fixnum.h"
|
4
|
+
#include "atomic_reference.h"
|
5
|
+
#include "ruby_193_compatible.h"
|
6
|
+
|
7
|
+
void atomic_fixnum_mark(void *value) {
|
8
|
+
rb_gc_mark_maybe((VALUE) value);
|
9
|
+
}
|
10
|
+
|
11
|
+
VALUE atomic_fixnum_allocate(VALUE klass) {
|
12
|
+
return rb_data_object_alloc(klass, (void *) Qnil, atomic_fixnum_mark, NULL);
|
13
|
+
}
|
14
|
+
|
15
|
+
VALUE method_atomic_fixnum_initialize(int argc, VALUE* argv, VALUE self) {
|
16
|
+
VALUE value = LL2NUM(0);
|
17
|
+
rb_check_arity(argc, 0, 1);
|
18
|
+
if (argc == 1) {
|
19
|
+
Check_Type(argv[0], T_FIXNUM);
|
20
|
+
value = argv[0];
|
21
|
+
}
|
22
|
+
DATA_PTR(self) = (void *) value;
|
23
|
+
return(self);
|
24
|
+
}
|
25
|
+
|
26
|
+
VALUE method_atomic_fixnum_value(VALUE self) {
|
27
|
+
return (VALUE) DATA_PTR(self);
|
28
|
+
}
|
29
|
+
|
30
|
+
VALUE method_atomic_fixnum_value_set(VALUE self, VALUE value) {
|
31
|
+
Check_Type(value, T_FIXNUM);
|
32
|
+
DATA_PTR(self) = (void *) value;
|
33
|
+
return(value);
|
34
|
+
}
|
35
|
+
|
36
|
+
VALUE method_atomic_fixnum_increment(VALUE self) {
|
37
|
+
long long value = NUM2LL((VALUE) DATA_PTR(self));
|
38
|
+
return method_atomic_fixnum_value_set(self, LL2NUM(value + 1));
|
39
|
+
}
|
40
|
+
|
41
|
+
VALUE method_atomic_fixnum_decrement(VALUE self) {
|
42
|
+
long long value = NUM2LL((VALUE) DATA_PTR(self));
|
43
|
+
return method_atomic_fixnum_value_set(self, LL2NUM(value - 1));
|
44
|
+
}
|
45
|
+
|
46
|
+
VALUE method_atomic_fixnum_compare_and_set(VALUE self, VALUE rb_expect, VALUE rb_update) {
|
47
|
+
Check_Type(rb_expect, T_FIXNUM);
|
48
|
+
Check_Type(rb_update, T_FIXNUM);
|
49
|
+
return ir_compare_and_set(self, rb_expect, rb_update);
|
50
|
+
}
|
@@ -0,0 +1,13 @@
|
|
1
|
+
#ifndef __ATOMIC_FIXNUM_H__
|
2
|
+
#define __ATOMIC_FIXNUM_H__
|
3
|
+
|
4
|
+
void atomic_fixnum_mark(void*);
|
5
|
+
VALUE atomic_fixnum_allocate(VALUE);
|
6
|
+
VALUE method_atomic_fixnum_initialize(int, VALUE*, VALUE);
|
7
|
+
VALUE method_atomic_fixnum_value(VALUE);
|
8
|
+
VALUE method_atomic_fixnum_value_set(VALUE, VALUE);
|
9
|
+
VALUE method_atomic_fixnum_increment(VALUE);
|
10
|
+
VALUE method_atomic_fixnum_decrement(VALUE);
|
11
|
+
VALUE method_atomic_fixnum_compare_and_set(VALUE, VALUE, VALUE);
|
12
|
+
|
13
|
+
#endif
|
@@ -0,0 +1,91 @@
|
|
1
|
+
#include <ruby.h>
|
2
|
+
/*#if defined(__sun)*/
|
3
|
+
/*#include <atomic.h>*/
|
4
|
+
/*#endif*/
|
5
|
+
|
6
|
+
/*#ifdef HAVE_LIBKERN_OSATOMIC_H*/
|
7
|
+
/*#include <libkern/OSAtomic.h>*/
|
8
|
+
/*#endif*/
|
9
|
+
|
10
|
+
#include "atomic_reference.h"
|
11
|
+
|
12
|
+
void ir_mark(void *value) {
|
13
|
+
rb_gc_mark_maybe((VALUE) value);
|
14
|
+
}
|
15
|
+
|
16
|
+
VALUE ir_alloc(VALUE klass) {
|
17
|
+
return rb_data_object_alloc(klass, (void *) Qnil, ir_mark, NULL);
|
18
|
+
}
|
19
|
+
|
20
|
+
VALUE ir_initialize(int argc, VALUE* argv, VALUE self) {
|
21
|
+
VALUE value = Qnil;
|
22
|
+
if (rb_scan_args(argc, argv, "01", &value) == 1) {
|
23
|
+
value = argv[0];
|
24
|
+
}
|
25
|
+
DATA_PTR(self) = (void *) value;
|
26
|
+
return Qnil;
|
27
|
+
}
|
28
|
+
|
29
|
+
VALUE ir_get(VALUE self) {
|
30
|
+
#if HAVE_GCC_SYNC
|
31
|
+
__sync_synchronize();
|
32
|
+
#elif defined _MSC_VER
|
33
|
+
MemoryBarrier();
|
34
|
+
#elif __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ >= 1050
|
35
|
+
OSMemoryBarrier();
|
36
|
+
#endif
|
37
|
+
return (VALUE) DATA_PTR(self);
|
38
|
+
}
|
39
|
+
|
40
|
+
VALUE ir_set(VALUE self, VALUE new_value) {
|
41
|
+
DATA_PTR(self) = (void *) new_value;
|
42
|
+
#if HAVE_GCC_SYNC
|
43
|
+
__sync_synchronize();
|
44
|
+
#elif defined _MSC_VER
|
45
|
+
MemoryBarrier();
|
46
|
+
#elif __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ >= 1050
|
47
|
+
OSMemoryBarrier();
|
48
|
+
#endif
|
49
|
+
return new_value;
|
50
|
+
}
|
51
|
+
|
52
|
+
VALUE ir_get_and_set(VALUE self, VALUE new_value) {
|
53
|
+
VALUE old_value = ir_get(self);
|
54
|
+
ir_set(self, new_value);
|
55
|
+
return old_value;
|
56
|
+
}
|
57
|
+
|
58
|
+
VALUE ir_compare_and_set(volatile VALUE self, VALUE expect_value, VALUE new_value) {
|
59
|
+
#if __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ >= 1050
|
60
|
+
if (OSAtomicCompareAndSwap64(expect_value, new_value, &DATA_PTR(self))) {
|
61
|
+
return Qtrue;
|
62
|
+
}
|
63
|
+
#elif defined(__sun)
|
64
|
+
/* Assuming VALUE is uintptr_t */
|
65
|
+
/* Based on the definition of uintptr_t from /usr/include/sys/int_types.h */
|
66
|
+
#if defined(_LP64) || defined(_I32LPx)
|
67
|
+
/* 64-bit: uintptr_t === unsigned long */
|
68
|
+
if (atomic_cas_ulong((uintptr_t *) &DATA_PTR(self), expect_value, new_value)) {
|
69
|
+
return Qtrue;
|
70
|
+
}
|
71
|
+
#else
|
72
|
+
/* 32-bit: uintptr_t === unsigned int */
|
73
|
+
if (atomic_cas_uint((uintptr_t *) &DATA_PTR(self), expect_value, new_value)) {
|
74
|
+
return Qtrue;
|
75
|
+
}
|
76
|
+
#endif
|
77
|
+
#elif defined _MSC_VER && defined _M_AMD64
|
78
|
+
if (InterlockedCompareExchange64((LONGLONG*)&DATA_PTR(self), new_value, expect_value)) {
|
79
|
+
return Qtrue;
|
80
|
+
}
|
81
|
+
#elif defined _MSC_VER && defined _M_IX86
|
82
|
+
if (InterlockedCompareExchange((LONG*)&DATA_PTR(self), new_value, expect_value)) {
|
83
|
+
return Qtrue;
|
84
|
+
}
|
85
|
+
#else
|
86
|
+
if (__sync_bool_compare_and_swap(&DATA_PTR(self), expect_value, new_value)) {
|
87
|
+
return Qtrue;
|
88
|
+
}
|
89
|
+
#endif
|
90
|
+
return Qfalse;
|
91
|
+
}
|
@@ -0,0 +1,20 @@
|
|
1
|
+
#ifndef __ATOMIC_REFERENCE_H__
|
2
|
+
#define __ATOMIC_REFERENCE_H__
|
3
|
+
|
4
|
+
#if defined(__sun)
|
5
|
+
#include <atomic.h>
|
6
|
+
#endif
|
7
|
+
|
8
|
+
#ifdef HAVE_LIBKERN_OSATOMIC_H
|
9
|
+
#include <libkern/OSAtomic.h>
|
10
|
+
#endif
|
11
|
+
|
12
|
+
void ir_mark(void*);
|
13
|
+
VALUE ir_alloc(VALUE);
|
14
|
+
VALUE ir_initialize(int, VALUE*, VALUE);
|
15
|
+
VALUE ir_get(VALUE);
|
16
|
+
VALUE ir_set(VALUE, VALUE);
|
17
|
+
VALUE ir_get_and_set(VALUE, VALUE);
|
18
|
+
VALUE ir_compare_and_set(volatile VALUE, VALUE, VALUE);
|
19
|
+
|
20
|
+
#endif
|
@@ -0,0 +1,58 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
|
3
|
+
$:.push File.join(File.dirname(__FILE__), '../../lib')
|
4
|
+
require 'extension_helper'
|
5
|
+
|
6
|
+
EXTENSION_NAME = 'concurrent_ruby_ext'
|
7
|
+
|
8
|
+
def create_dummy_makefile
|
9
|
+
File.open('Makefile', 'w') do |f|
|
10
|
+
f.puts 'all:'
|
11
|
+
f.puts 'install:'
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
if defined?(JRUBY_VERSION) || ! Concurrent.allow_c_extensions?
|
16
|
+
create_dummy_makefile
|
17
|
+
warn 'C optimizations are not supported on this version of Ruby.'
|
18
|
+
else
|
19
|
+
begin
|
20
|
+
|
21
|
+
require 'mkmf'
|
22
|
+
dir_config(EXTENSION_NAME)
|
23
|
+
|
24
|
+
have_header "libkern/OSAtomic.h"
|
25
|
+
|
26
|
+
def compiler_is_gcc
|
27
|
+
if CONFIG["GCC"] && CONFIG["GCC"] != ""
|
28
|
+
return true
|
29
|
+
elsif ( # This could stand to be more generic... but I am afraid.
|
30
|
+
CONFIG["CC"] =~ /\bgcc\b/
|
31
|
+
)
|
32
|
+
return true
|
33
|
+
end
|
34
|
+
return false
|
35
|
+
end
|
36
|
+
|
37
|
+
if compiler_is_gcc
|
38
|
+
case CONFIG["arch"]
|
39
|
+
when /mswin32|mingw|solaris/
|
40
|
+
$CFLAGS += " -march=native"
|
41
|
+
when 'i686-linux'
|
42
|
+
$CFLAGS += " -march=i686"
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
try_run(<<CODE,$CFLAGS) && ($defs << '-DHAVE_GCC_SYNC')
|
47
|
+
int main() {
|
48
|
+
__sync_synchronize();
|
49
|
+
return 0;
|
50
|
+
}
|
51
|
+
CODE
|
52
|
+
|
53
|
+
create_makefile(EXTENSION_NAME)
|
54
|
+
rescue
|
55
|
+
create_dummy_makefile
|
56
|
+
warn 'C optimizations cannot be compiled on this version of Ruby.'
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
#include <ruby.h>
|
2
|
+
|
3
|
+
#include "atomic_reference.h"
|
4
|
+
#include "atomic_boolean.h"
|
5
|
+
#include "atomic_fixnum.h"
|
6
|
+
|
7
|
+
// module and class definitions
|
8
|
+
|
9
|
+
static VALUE rb_mConcurrent;
|
10
|
+
static VALUE rb_cAtomic;
|
11
|
+
static VALUE rb_cAtomicBoolean;
|
12
|
+
static VALUE rb_cAtomicFixnum;
|
13
|
+
|
14
|
+
// Init_concurrent_ruby_ext
|
15
|
+
|
16
|
+
void Init_concurrent_ruby_ext() {
|
17
|
+
|
18
|
+
// define modules and classes
|
19
|
+
rb_mConcurrent = rb_define_module("Concurrent");
|
20
|
+
rb_cAtomic = rb_define_class_under(rb_mConcurrent, "CAtomic", rb_cObject);
|
21
|
+
rb_cAtomicBoolean = rb_define_class_under(rb_mConcurrent, "CAtomicBoolean", rb_cObject);
|
22
|
+
rb_cAtomicFixnum = rb_define_class_under(rb_mConcurrent, "CAtomicFixnum", rb_cObject);
|
23
|
+
|
24
|
+
// CAtomic
|
25
|
+
rb_define_alloc_func(rb_cAtomic, ir_alloc);
|
26
|
+
rb_define_method(rb_cAtomic, "initialize", ir_initialize, -1);
|
27
|
+
rb_define_method(rb_cAtomic, "get", ir_get, 0);
|
28
|
+
rb_define_method(rb_cAtomic, "set", ir_set, 1);
|
29
|
+
rb_define_method(rb_cAtomic, "get_and_set", ir_get_and_set, 1);
|
30
|
+
rb_define_method(rb_cAtomic, "_compare_and_set", ir_compare_and_set, 2);
|
31
|
+
rb_define_alias(rb_cAtomic, "value", "get");
|
32
|
+
rb_define_alias(rb_cAtomic, "value=", "set");
|
33
|
+
rb_define_alias(rb_cAtomic, "swap", "get_and_set");
|
34
|
+
|
35
|
+
// CAtomicBoolean
|
36
|
+
rb_define_alloc_func(rb_cAtomicBoolean, atomic_boolean_allocate);
|
37
|
+
rb_define_method(rb_cAtomicBoolean, "initialize", method_atomic_boolean_initialize, -1);
|
38
|
+
rb_define_method(rb_cAtomicBoolean, "value", method_atomic_boolean_value, 0);
|
39
|
+
rb_define_method(rb_cAtomicBoolean, "value=", method_atomic_boolean_value_set, 1);
|
40
|
+
rb_define_method(rb_cAtomicBoolean, "true?", method_atomic_boolean_true_question, 0);
|
41
|
+
rb_define_method(rb_cAtomicBoolean, "false?", method_atomic_boolean_false_question, 0);
|
42
|
+
rb_define_method(rb_cAtomicBoolean, "make_true", method_atomic_boolean_make_true, 0);
|
43
|
+
rb_define_method(rb_cAtomicBoolean, "make_false", method_atomic_boolean_make_false, 0);
|
44
|
+
|
45
|
+
// CAtomicFixnum
|
46
|
+
rb_define_const(rb_cAtomicFixnum, "MIN_VALUE", LL2NUM(LLONG_MIN));
|
47
|
+
rb_define_const(rb_cAtomicFixnum, "MAX_VALUE", LL2NUM(LLONG_MAX));
|
48
|
+
rb_define_alloc_func(rb_cAtomicFixnum, atomic_fixnum_allocate);
|
49
|
+
rb_define_method(rb_cAtomicFixnum, "initialize", method_atomic_fixnum_initialize, -1);
|
50
|
+
rb_define_method(rb_cAtomicFixnum, "value", method_atomic_fixnum_value, 0);
|
51
|
+
rb_define_method(rb_cAtomicFixnum, "value=", method_atomic_fixnum_value_set, 1);
|
52
|
+
rb_define_method(rb_cAtomicFixnum, "increment", method_atomic_fixnum_increment, 0);
|
53
|
+
rb_define_method(rb_cAtomicFixnum, "decrement", method_atomic_fixnum_decrement, 0);
|
54
|
+
rb_define_method(rb_cAtomicFixnum, "compare_and_set", method_atomic_fixnum_compare_and_set, 2);
|
55
|
+
rb_define_alias(rb_cAtomicFixnum, "up", "increment");
|
56
|
+
rb_define_alias(rb_cAtomicFixnum, "down", "decrement");
|
57
|
+
}
|
@@ -0,0 +1,28 @@
|
|
1
|
+
#ifndef rb_check_arity
|
2
|
+
|
3
|
+
// https://github.com/ruby/ruby/blob/ruby_2_0_0/include/ruby/intern.h
|
4
|
+
// rb_check_arity was added in Ruby 2.0
|
5
|
+
|
6
|
+
#define UNLIMITED_ARGUMENTS (-1)
|
7
|
+
|
8
|
+
static inline void rb_error_arity(int argc, int min, int max)
|
9
|
+
{
|
10
|
+
VALUE err_mess = 0;
|
11
|
+
if (min == max) {
|
12
|
+
err_mess = rb_sprintf("wrong number of arguments (%d for %d)", argc, min);
|
13
|
+
}
|
14
|
+
else if (max == UNLIMITED_ARGUMENTS) {
|
15
|
+
err_mess = rb_sprintf("wrong number of arguments (%d for %d+)", argc, min);
|
16
|
+
}
|
17
|
+
else {
|
18
|
+
err_mess = rb_sprintf("wrong number of arguments (%d for %d..%d)", argc, min, max);
|
19
|
+
}
|
20
|
+
rb_raise(rb_eTypeError, err_mess);
|
21
|
+
}
|
22
|
+
|
23
|
+
#define rb_check_arity(argc, min, max) do { \
|
24
|
+
if (((argc) < (min)) || ((argc) > (max) && (max) != UNLIMITED_ARGUMENTS)) \
|
25
|
+
rb_error_arity(argc, min, max); \
|
26
|
+
} while(0)
|
27
|
+
|
28
|
+
#endif
|
Binary file
|
@@ -0,0 +1,50 @@
|
|
1
|
+
require 'concurrent/atomic_reference/concurrent_update_error'
|
2
|
+
|
3
|
+
module Concurrent
|
4
|
+
|
5
|
+
# Define update methods that use direct paths
|
6
|
+
module AtomicDirectUpdate
|
7
|
+
|
8
|
+
# @!macro [attach] atomic_reference_method_update
|
9
|
+
#
|
10
|
+
# Pass the current value to the given block, replacing it
|
11
|
+
# with the block's result. May retry if the value changes
|
12
|
+
# during the block's execution.
|
13
|
+
#
|
14
|
+
# @yield [Object] Calculate a new value for the atomic reference using
|
15
|
+
# given (old) value
|
16
|
+
# @yieldparam [Object] old_value the starting value of the atomic reference
|
17
|
+
#
|
18
|
+
# @return [Object] the new value
|
19
|
+
def update
|
20
|
+
true until compare_and_set(old_value = get, new_value = yield(old_value))
|
21
|
+
new_value
|
22
|
+
end
|
23
|
+
|
24
|
+
# @!macro [attach] atomic_reference_method_try_update
|
25
|
+
#
|
26
|
+
# Pass the current value to the given block, replacing it
|
27
|
+
# with the block's result. Raise an exception if the update
|
28
|
+
# fails.
|
29
|
+
#
|
30
|
+
# @yield [Object] Calculate a new value for the atomic reference using
|
31
|
+
# given (old) value
|
32
|
+
# @yieldparam [Object] old_value the starting value of the atomic reference
|
33
|
+
#
|
34
|
+
# @return [Object] the new value
|
35
|
+
#
|
36
|
+
# @raise [Concurrent::ConcurrentUpdateError] if the update fails
|
37
|
+
def try_update
|
38
|
+
old_value = get
|
39
|
+
new_value = yield old_value
|
40
|
+
unless compare_and_set(old_value, new_value)
|
41
|
+
if $VERBOSE
|
42
|
+
raise ConcurrentUpdateError, "Update failed"
|
43
|
+
else
|
44
|
+
raise ConcurrentUpdateError, "Update failed", ConcurrentUpdateError::CONC_UP_ERR_BACKTRACE
|
45
|
+
end
|
46
|
+
end
|
47
|
+
new_value
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module Concurrent
|
2
|
+
|
3
|
+
# Special "compare and set" handling of numeric values.
|
4
|
+
module AtomicNumericCompareAndSetWrapper
|
5
|
+
|
6
|
+
# @!macro atomic_reference_method_compare_and_set
|
7
|
+
def compare_and_set(old_value, new_value)
|
8
|
+
if old_value.kind_of? Numeric
|
9
|
+
while true
|
10
|
+
old = get
|
11
|
+
|
12
|
+
return false unless old.kind_of? Numeric
|
13
|
+
|
14
|
+
return false unless old == old_value
|
15
|
+
|
16
|
+
result = _compare_and_set(old, new_value)
|
17
|
+
return result if result
|
18
|
+
end
|
19
|
+
else
|
20
|
+
_compare_and_set(old_value, new_value)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
alias_method :compare_and_swap, :compare_and_set
|
24
|
+
end
|
25
|
+
end
|
metadata
ADDED
@@ -0,0 +1,78 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: concurrent-ruby-ext
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0.pre1
|
5
|
+
platform: x64-mingw32
|
6
|
+
authors:
|
7
|
+
- Jerry D'Antonio
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-12-15 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: concurrent-ruby
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ~>
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 0.8.0.pre1
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ~>
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 0.8.0.pre1
|
27
|
+
description: ! " Modern concurrency tools including agents, futures, promises,
|
28
|
+
thread pools, actors, supervisors, and more.\n Inspired by Erlang, Clojure, Go,
|
29
|
+
JavaScript, actors, and classic concurrency patterns.\n"
|
30
|
+
email: jerry.dantonio@gmail.com
|
31
|
+
executables: []
|
32
|
+
extensions: []
|
33
|
+
extra_rdoc_files:
|
34
|
+
- README.md
|
35
|
+
- LICENSE.txt
|
36
|
+
- CHANGELOG.md
|
37
|
+
files:
|
38
|
+
- CHANGELOG.md
|
39
|
+
- LICENSE.txt
|
40
|
+
- README.md
|
41
|
+
- ext/concurrent_ruby_ext/atomic_boolean.c
|
42
|
+
- ext/concurrent_ruby_ext/atomic_boolean.h
|
43
|
+
- ext/concurrent_ruby_ext/atomic_fixnum.c
|
44
|
+
- ext/concurrent_ruby_ext/atomic_fixnum.h
|
45
|
+
- ext/concurrent_ruby_ext/atomic_reference.c
|
46
|
+
- ext/concurrent_ruby_ext/atomic_reference.h
|
47
|
+
- ext/concurrent_ruby_ext/extconf.rb
|
48
|
+
- ext/concurrent_ruby_ext/rb_concurrent.c
|
49
|
+
- ext/concurrent_ruby_ext/ruby_193_compatible.h
|
50
|
+
- lib/2.0/concurrent_ruby_ext.so
|
51
|
+
- lib/concurrent/atomic_reference/concurrent_update_error.rb
|
52
|
+
- lib/concurrent/atomic_reference/direct_update.rb
|
53
|
+
- lib/concurrent/atomic_reference/numeric_cas_wrapper.rb
|
54
|
+
homepage: http://www.concurrent-ruby.com
|
55
|
+
licenses:
|
56
|
+
- MIT
|
57
|
+
metadata: {}
|
58
|
+
post_install_message:
|
59
|
+
rdoc_options: []
|
60
|
+
require_paths:
|
61
|
+
- lib
|
62
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
63
|
+
requirements:
|
64
|
+
- - ! '>='
|
65
|
+
- !ruby/object:Gem::Version
|
66
|
+
version: 1.9.3
|
67
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
68
|
+
requirements:
|
69
|
+
- - ! '>'
|
70
|
+
- !ruby/object:Gem::Version
|
71
|
+
version: 1.3.1
|
72
|
+
requirements: []
|
73
|
+
rubyforge_project:
|
74
|
+
rubygems_version: 2.4.5
|
75
|
+
signing_key:
|
76
|
+
specification_version: 4
|
77
|
+
summary: C extensions to optimize concurrent-ruby under MRI.
|
78
|
+
test_files: []
|