thread_safe 0.1.1-java
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +21 -0
- data/Gemfile +4 -0
- data/LICENSE +144 -0
- data/README.md +34 -0
- data/Rakefile +36 -0
- data/examples/bench_cache.rb +35 -0
- data/ext/org/jruby/ext/thread_safe/JRubyCacheBackendLibrary.java +200 -0
- data/ext/org/jruby/ext/thread_safe/jsr166e/ConcurrentHashMapV8.java +3842 -0
- data/ext/org/jruby/ext/thread_safe/jsr166e/LongAdder.java +204 -0
- data/ext/org/jruby/ext/thread_safe/jsr166e/Striped64.java +342 -0
- data/ext/org/jruby/ext/thread_safe/jsr166y/ThreadLocalRandom.java +199 -0
- data/ext/thread_safe/JrubyCacheBackendService.java +15 -0
- data/lib/thread_safe.rb +65 -0
- data/lib/thread_safe/atomic_reference_cache_backend.rb +922 -0
- data/lib/thread_safe/cache.rb +137 -0
- data/lib/thread_safe/mri_cache_backend.rb +62 -0
- data/lib/thread_safe/non_concurrent_cache_backend.rb +133 -0
- data/lib/thread_safe/synchronized_cache_backend.rb +76 -0
- data/lib/thread_safe/synchronized_delegator.rb +35 -0
- data/lib/thread_safe/util.rb +16 -0
- data/lib/thread_safe/util/adder.rb +59 -0
- data/lib/thread_safe/util/atomic_reference.rb +12 -0
- data/lib/thread_safe/util/cheap_lockable.rb +105 -0
- data/lib/thread_safe/util/power_of_two_tuple.rb +26 -0
- data/lib/thread_safe/util/striped64.rb +226 -0
- data/lib/thread_safe/util/volatile.rb +62 -0
- data/lib/thread_safe/util/volatile_tuple.rb +46 -0
- data/lib/thread_safe/util/xor_shift_random.rb +39 -0
- data/lib/thread_safe/version.rb +3 -0
- data/test/test_array.rb +20 -0
- data/test/test_cache.rb +792 -0
- data/test/test_cache_loops.rb +453 -0
- data/test/test_hash.rb +20 -0
- data/test/test_helper.rb +73 -0
- data/test/test_synchronized_delegator.rb +42 -0
- data/thread_safe.gemspec +21 -0
- metadata +100 -0
data/test/test_hash.rb
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
require 'thread_safe'
|
3
|
+
|
4
|
+
class TestHash < Test::Unit::TestCase
|
5
|
+
def test_concurrency
|
6
|
+
hsh = ThreadSafe::Hash.new
|
7
|
+
assert_nothing_raised do
|
8
|
+
(1..100).map do |i|
|
9
|
+
Thread.new do
|
10
|
+
1000.times do |j|
|
11
|
+
hsh[i*1000+j] = i
|
12
|
+
hsh.each {|k,v| k + v}
|
13
|
+
hsh[i*1000+j]
|
14
|
+
hsh.delete(i*1000+j)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end.map(&:join)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
data/test/test_helper.rb
ADDED
@@ -0,0 +1,73 @@
|
|
1
|
+
require 'thread'
|
2
|
+
|
3
|
+
module ThreadSafe
|
4
|
+
module Test
|
5
|
+
class Latch
|
6
|
+
def initialize(count = 1)
|
7
|
+
@count = count
|
8
|
+
@mutex = Mutex.new
|
9
|
+
@cond = ConditionVariable.new
|
10
|
+
end
|
11
|
+
|
12
|
+
def release
|
13
|
+
@mutex.synchronize do
|
14
|
+
@count -= 1 if @count > 0
|
15
|
+
@cond.broadcast if @count.zero?
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def await
|
20
|
+
@mutex.synchronize do
|
21
|
+
@cond.wait @mutex if @count > 0
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
class Barrier < Latch
|
27
|
+
def await
|
28
|
+
@mutex.synchronize do
|
29
|
+
if @count.zero? # fall through
|
30
|
+
elsif @count > 0
|
31
|
+
@count -= 1
|
32
|
+
@count.zero? ? @cond.broadcast : @cond.wait(@mutex)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
class HashCollisionKey
|
39
|
+
attr_reader :hash, :key
|
40
|
+
def initialize(key, hash = key.hash % 3)
|
41
|
+
@key = key
|
42
|
+
@hash = hash
|
43
|
+
end
|
44
|
+
|
45
|
+
def eql?(other)
|
46
|
+
other.kind_of?(self.class) && @key.eql?(other.key)
|
47
|
+
end
|
48
|
+
|
49
|
+
def even?
|
50
|
+
@key.even?
|
51
|
+
end
|
52
|
+
|
53
|
+
def <=>(other)
|
54
|
+
@key <=> other.key
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
# having 4 separate HCK classes helps for a more thorough CHMV8 testing
|
59
|
+
class HashCollisionKey2 < HashCollisionKey; end
|
60
|
+
class HashCollisionKeyNoCompare < HashCollisionKey
|
61
|
+
def <=>(other)
|
62
|
+
0
|
63
|
+
end
|
64
|
+
end
|
65
|
+
class HashCollisionKey4 < HashCollisionKeyNoCompare; end
|
66
|
+
|
67
|
+
HASH_COLLISION_CLASSES = [HashCollisionKey, HashCollisionKey2, HashCollisionKeyNoCompare, HashCollisionKey4]
|
68
|
+
|
69
|
+
def self.HashCollisionKey(key)
|
70
|
+
HASH_COLLISION_CLASSES[rand(4)].new(key)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
require 'thread_safe/synchronized_delegator.rb'
|
3
|
+
|
4
|
+
class TestSynchronizedDelegator < Test::Unit::TestCase
|
5
|
+
def test_wraps_array
|
6
|
+
ary = []
|
7
|
+
sync_ary = SynchronizedDelegator.new(ary)
|
8
|
+
|
9
|
+
ary << 1
|
10
|
+
assert_equal 1, sync_ary[0]
|
11
|
+
end
|
12
|
+
|
13
|
+
def test_synchronizes_access
|
14
|
+
ary = []
|
15
|
+
sync_ary = SynchronizedDelegator.new(ary)
|
16
|
+
|
17
|
+
t1_continue = false
|
18
|
+
t2_continue = false
|
19
|
+
|
20
|
+
t1 = Thread.new do
|
21
|
+
sync_ary << 1
|
22
|
+
sync_ary.each do
|
23
|
+
t2_continue = true
|
24
|
+
Thread.pass until t1_continue
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
t2 = Thread.new do
|
29
|
+
Thread.pass until t2_continue
|
30
|
+
sync_ary << 2
|
31
|
+
end
|
32
|
+
|
33
|
+
Thread.pass until t2.status == 'sleep'
|
34
|
+
assert_equal 1, ary.size
|
35
|
+
|
36
|
+
t1_continue = true
|
37
|
+
t1.join
|
38
|
+
t2.join
|
39
|
+
|
40
|
+
assert_equal 2, sync_ary.size
|
41
|
+
end
|
42
|
+
end
|
data/thread_safe.gemspec
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
require File.expand_path('../lib/thread_safe/version', __FILE__)
|
3
|
+
|
4
|
+
Gem::Specification.new do |gem|
|
5
|
+
gem.authors = ["Charles Oliver Nutter"]
|
6
|
+
gem.email = ["headius@headius.com"]
|
7
|
+
gem.description = %q{Thread-safe collections and utilities for Ruby}
|
8
|
+
gem.summary = %q{A collection of data structures and utilities to make thread-safe programming in Ruby easier}
|
9
|
+
gem.homepage = "https://github.com/headius/thread_safe"
|
10
|
+
|
11
|
+
gem.files = `git ls-files`.split($\)
|
12
|
+
gem.platform = 'java' if defined?(JRUBY_VERSION)
|
13
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
14
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
15
|
+
gem.name = "thread_safe"
|
16
|
+
gem.require_paths = ["lib"]
|
17
|
+
gem.version = Threadsafe::VERSION
|
18
|
+
gem.license = "Apache-2.0"
|
19
|
+
|
20
|
+
gem.add_dependency 'atomic'
|
21
|
+
end
|
metadata
ADDED
@@ -0,0 +1,100 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: thread_safe
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.1
|
5
|
+
platform: java
|
6
|
+
authors:
|
7
|
+
- Charles Oliver Nutter
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2013-07-23 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: atomic
|
15
|
+
version_requirements: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - '>='
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
requirement: !ruby/object:Gem::Requirement
|
21
|
+
requirements:
|
22
|
+
- - '>='
|
23
|
+
- !ruby/object:Gem::Version
|
24
|
+
version: '0'
|
25
|
+
prerelease: false
|
26
|
+
type: :runtime
|
27
|
+
description: Thread-safe collections and utilities for Ruby
|
28
|
+
email:
|
29
|
+
- headius@headius.com
|
30
|
+
executables: []
|
31
|
+
extensions: []
|
32
|
+
extra_rdoc_files: []
|
33
|
+
files:
|
34
|
+
- .gitignore
|
35
|
+
- Gemfile
|
36
|
+
- LICENSE
|
37
|
+
- README.md
|
38
|
+
- Rakefile
|
39
|
+
- examples/bench_cache.rb
|
40
|
+
- ext/org/jruby/ext/thread_safe/JRubyCacheBackendLibrary.java
|
41
|
+
- ext/org/jruby/ext/thread_safe/jsr166e/ConcurrentHashMapV8.java
|
42
|
+
- ext/org/jruby/ext/thread_safe/jsr166e/LongAdder.java
|
43
|
+
- ext/org/jruby/ext/thread_safe/jsr166e/Striped64.java
|
44
|
+
- ext/org/jruby/ext/thread_safe/jsr166y/ThreadLocalRandom.java
|
45
|
+
- ext/thread_safe/JrubyCacheBackendService.java
|
46
|
+
- lib/thread_safe.rb
|
47
|
+
- lib/thread_safe/atomic_reference_cache_backend.rb
|
48
|
+
- lib/thread_safe/cache.rb
|
49
|
+
- lib/thread_safe/mri_cache_backend.rb
|
50
|
+
- lib/thread_safe/non_concurrent_cache_backend.rb
|
51
|
+
- lib/thread_safe/synchronized_cache_backend.rb
|
52
|
+
- lib/thread_safe/synchronized_delegator.rb
|
53
|
+
- lib/thread_safe/util.rb
|
54
|
+
- lib/thread_safe/util/adder.rb
|
55
|
+
- lib/thread_safe/util/atomic_reference.rb
|
56
|
+
- lib/thread_safe/util/cheap_lockable.rb
|
57
|
+
- lib/thread_safe/util/power_of_two_tuple.rb
|
58
|
+
- lib/thread_safe/util/striped64.rb
|
59
|
+
- lib/thread_safe/util/volatile.rb
|
60
|
+
- lib/thread_safe/util/volatile_tuple.rb
|
61
|
+
- lib/thread_safe/util/xor_shift_random.rb
|
62
|
+
- lib/thread_safe/version.rb
|
63
|
+
- test/test_array.rb
|
64
|
+
- test/test_cache.rb
|
65
|
+
- test/test_cache_loops.rb
|
66
|
+
- test/test_hash.rb
|
67
|
+
- test/test_helper.rb
|
68
|
+
- test/test_synchronized_delegator.rb
|
69
|
+
- thread_safe.gemspec
|
70
|
+
homepage: https://github.com/headius/thread_safe
|
71
|
+
licenses:
|
72
|
+
- Apache-2.0
|
73
|
+
metadata: {}
|
74
|
+
post_install_message:
|
75
|
+
rdoc_options: []
|
76
|
+
require_paths:
|
77
|
+
- lib
|
78
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - '>='
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
84
|
+
requirements:
|
85
|
+
- - '>='
|
86
|
+
- !ruby/object:Gem::Version
|
87
|
+
version: '0'
|
88
|
+
requirements: []
|
89
|
+
rubyforge_project:
|
90
|
+
rubygems_version: 2.0.3
|
91
|
+
signing_key:
|
92
|
+
specification_version: 4
|
93
|
+
summary: A collection of data structures and utilities to make thread-safe programming in Ruby easier
|
94
|
+
test_files:
|
95
|
+
- test/test_array.rb
|
96
|
+
- test/test_cache.rb
|
97
|
+
- test/test_cache_loops.rb
|
98
|
+
- test/test_hash.rb
|
99
|
+
- test/test_helper.rb
|
100
|
+
- test/test_synchronized_delegator.rb
|