thread_safe 0.1.1-java
Sign up to get free protection for your applications and to get access to all the features.
- 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
|