Skip to content

Commit d58679c

Browse files
committed
Merge pull request #386 from ruby-concurrency/thread_safe
Import `thread_safe` gem
2 parents 1fbf9d5 + 5ea48b8 commit d58679c

Some content is hidden

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

52 files changed

+13172
-81
lines changed

.travis.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,4 +27,8 @@ matrix:
2727
- rvm: jruby-head
2828
- rvm: 1.9.3
2929

30+
before_script:
31+
- "echo $JAVA_OPTS"
32+
- "export JAVA_OPTS=-Xmx1024m"
33+
3034
script: RUBYOPT=-w bundle exec rake ci

README.md

Lines changed: 43 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -62,50 +62,57 @@ This library contains a variety of concurrency abstractions at high and low leve
6262
#### General-purpose Concurrency Abstractions
6363

6464
* [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.
65-
* [Atom](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/Atom.html): A way to manage shared, synchronous, independent state.
6665
* [Future](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/Future.html): An asynchronous operation that produces a value.
6766
* [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.
6867
* [Promise](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/Promise.html): Similar to Futures, with more features.
6968
* [ScheduledTask](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/ScheduledTask.html): Like a Future scheduled for a specific future time.
7069
* [TimerTask](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/TimerTask.html): A Thread that periodically wakes up to perform work at regular intervals.
7170

72-
#### Thread-safe Value Objects
71+
#### Thread-safe Value Objects, Structures, and Collections
72+
73+
Collection classes that were originally part of the (deprecated) `thread_safe` gem:
74+
75+
* [Array](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/Array.html) A thread-safe subclass of Ruby's standard [Array](http://ruby-doc.org/core-2.2.0/Array.html).
76+
* [Hash](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/Hash.html) A thread-safe subclass of Ruby's standard [Hash](http://ruby-doc.org/core-2.2.0/Hash.html).
77+
* [Map](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/Map.html) A hash-like object that should have much better performance characteristics, especially under high concurrency, than `Concurrent::Hash`.
78+
* [Tuple](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/Tuple.html) A fixed size array with volatile (synchronized, thread safe) getters/setters.
79+
80+
Value objects inspired by other languages:
7381

74-
* `Maybe` A thread-safe, immutable object representing an optional value, based on
82+
* [Atom](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/Atom.html): A way to manage shared, synchronous, independent state.
83+
* [Maybe](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/Maybe.html) A thread-safe, immutable object representing an optional value, based on
7584
[Haskell Data.Maybe](https://hackage.haskell.org/package/base-4.2.0.1/docs/Data-Maybe.html).
76-
* `Delay` Lazy evaluation of a block yielding an immutable result. Based on Clojure's
85+
* [Delay](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/Delay.html) Lazy evaluation of a block yielding an immutable result. Based on Clojure's
7786
[delay](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/Delay.html).
7887

79-
#### Thread-safe Structures
88+
Structure classes derived from Ruby's [Struct](http://ruby-doc.org/core-2.2.0/Struct.html):
89+
90+
* [ImmutableStruct](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/ImmutableStruct.html) Immutable struct where values are set at construction and cannot be changed later.
91+
* [MutableStruct](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/MutableStruct.html) Synchronized, mutable struct where values can be safely changed at any time.
92+
* [SettableStruct](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/SettableStruct.html) Synchronized, write-once struct where values can be set at most once, either at construction or any time thereafter.
8093

81-
Derived from Ruby's [Struct](http://ruby-doc.org/core-2.2.0/Struct.html):
94+
Thread-safe variables:
8295

83-
* `ImmutableStruct` Immutable struct where values are set at construction and cannot be changed later.
84-
* `MutableStruct` Synchronized, mutable struct where values can be safely changed at any time.
85-
* `SettableStruct` Synchronized, write-once struct where values can be set at most once, either at construction or any time thereafter.
96+
* [AtomicBoolean](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/AtomicBoolean.html) A boolean value that can be updated atomically.
97+
* [AtomicFixnum](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/AtomicFixnum.html) A numeric value that can be updated atomically.
98+
* [AtomicReference](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/MutexAtomic.html) An object reference that may be updated atomically.
99+
* [ThreadLocalVar](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/ThreadLocalVar.html) A variable where the value is different for each thread.
86100

87101
#### Java-inspired ThreadPools and Other Executors
88102

89-
* See [ThreadPool](http://ruby-concurrency.github.io/concurrent-ruby/file.thread_pools.html) overview, which also contains a list of other Executors available.
103+
* See the [thread pool](http://ruby-concurrency.github.io/concurrent-ruby/file.thread_pools.html) overview, which also contains a list of other Executors available.
90104

91105
#### Thread Synchronization Classes and Algorithms
92106

93-
* [CountdownLatch](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/CountDownLatch.html)
94-
* [CyclicBarrier](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/CyclicBarrier.html)
95-
* [Event](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/Event.html)
96-
* [Semaphore](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/Semaphore.html)
97-
98-
#### Thread-safe Variables
99-
100-
* [AtomicBoolean](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/AtomicBoolean.html)
101-
* [AtomicFixnum](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/AtomicFixnum.html)
102-
* [AtomicReference](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/MutexAtomic.html)
103-
* [I-Structures](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/IVar.html) (IVar)
104-
* [M-Structures](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/MVar.html) (MVar)
105-
* [Thread-local variables](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/ThreadLocalVar.html)
106-
* [Software transactional memory](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/TVar.html) (TVar)
107-
* [ReadWriteLock](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/ReadWriteLock.html)
108-
* [ReentrantReadWriteLock](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/ReentrantReadWriteLock.html)
107+
* [CountdownLatch](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/CountDownLatch.html) A synchronization object that allows one thread to wait on multiple other threads.
108+
* [CyclicBarrier](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/CyclicBarrier.html) A synchronization aid that allows a set of threads to all wait for each other to reach a common barrier point.
109+
* [Event](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/Event.html) Old school kernel-style event.
110+
* [I-Structure](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/IVar.html) (IVar) Similar to a "future" but can be manually assigned once, after which it becomes immutable.
111+
* [M-Structure](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/MVar.html) (MVar) A synchronized single element container.
112+
* [ReadWriteLock](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/ReadWriteLock.html) A lock that supports multiple readers but only one writer.
113+
* [ReentrantReadWriteLock](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/ReentrantReadWriteLock.html) A read/write lock with reentrant and upgrade features.
114+
* [Semaphore](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/Semaphore.html) A counting-based locking mechanism that uses permits.
115+
* [Software transactional memory](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/TVar.html) (TVar) A transactional variable - a single-element container that is used as part of a transaction.
109116

110117
### Edge Features
111118

@@ -127,8 +134,8 @@ be obeyed though. Features developed in `concurrent-ruby-edge` are expected to m
127134
Communicating Sequential Processes (CSP).
128135
* [Exchanger](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/Exchanger.html)
129136
* [LazyRegister](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/LazyRegister.html)
130-
* [Atomic Markable Reference](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/Edge/AtomicMarkableReference.html)
131-
* [LockFreeLinked Set](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/Edge/LockFreeLinkedSet.html)
137+
* [AtomicMarkableReference](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/Edge/AtomicMarkableReference.html)
138+
* [LockFreeLinkedSet](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/Edge/LockFreeLinkedSet.html)
132139
* [LockFreeStack](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/Edge/LockFreeStack.html)
133140

134141
#### Statuses:
@@ -272,11 +279,17 @@ bundle exec rake compile # Compile all the extensions
272279
## Maintainers
273280

274281
* [Jerry D'Antonio](https://github.com/jdantonio) (creator)
282+
* [Petr Chalupa](https://github.com/pitr-ch)
275283
* [Michele Della Torre](https://github.com/mighe)
276284
* [Chris Seaton](https://github.com/chrisseaton)
277-
* [Lucas Allan](https://github.com/lucasallan)
278-
* [Petr Chalupa](https://github.com/pitr-ch)
279285
* [Paweł Obrok](https://github.com/obrok)
286+
* [Lucas Allan](https://github.com/lucasallan)
287+
288+
### Special Thanks
289+
290+
* [Brian Durand](https://github.com/bdurand) for the `ref` gem
291+
* [Charles Oliver Nutter](https://github.com/headius) for the `atomic` and `thread_safe` gems
292+
* [thedarkone](https://github.com/thedarkone) for the `thread_safe` gem
280293

281294
## Contributing
282295

examples/bench_map.rb

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
#!/usr/bin/env ruby
2+
3+
require "benchmark"
4+
require "concurrent"
5+
6+
hash = {}
7+
map = Concurrent::Map.new
8+
9+
ENTRIES = 10_000
10+
11+
ENTRIES.times do |i|
12+
hash[i] = i
13+
map[i] = i
14+
end
15+
16+
TESTS = 40_000_000
17+
Benchmark.bmbm do |results|
18+
key = rand(10_000)
19+
20+
results.report('Hash#[]') do
21+
TESTS.times { hash[key] }
22+
end
23+
24+
results.report('Map#[]') do
25+
TESTS.times { map[key] }
26+
end
27+
28+
results.report('Hash#each_pair') do
29+
(TESTS / ENTRIES).times { hash.each_pair {|k,v| v} }
30+
end
31+
32+
results.report('Map#each_pair') do
33+
(TESTS / ENTRIES).times { map.each_pair {|k,v| v} }
34+
end
35+
end

ext/ConcurrentRubyExtService.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import org.jruby.Ruby;
44
import org.jruby.runtime.load.BasicLibraryService;
5+
import com.concurrent_ruby.ext.JRubyMapBackendLibrary;
56

67
public class ConcurrentRubyExtService implements BasicLibraryService {
78
public boolean basicLoad(final Ruby runtime) throws IOException {
@@ -10,6 +11,7 @@ public boolean basicLoad(final Ruby runtime) throws IOException {
1011
new com.concurrent_ruby.ext.JavaAtomicFixnumLibrary().load(runtime, false);
1112
new com.concurrent_ruby.ext.JavaSemaphoreLibrary().load(runtime, false);
1213
new com.concurrent_ruby.ext.SynchronizationLibrary().load(runtime, false);
14+
new com.concurrent_ruby.ext.JRubyMapBackendLibrary().load(runtime, false);
1315
return true;
1416
}
1517
}

0 commit comments

Comments
 (0)