thread_safe 0.1.3 → 0.2.0

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.
Files changed (41) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +24 -0
  3. data/README.md +19 -5
  4. data/Rakefile +13 -6
  5. data/examples/bench_cache.rb +1 -1
  6. data/ext/org/jruby/ext/thread_safe/JRubyCacheBackendLibrary.java +54 -15
  7. data/ext/org/jruby/ext/thread_safe/jsr166e/ConcurrentHashMap.java +28 -0
  8. data/ext/org/jruby/ext/thread_safe/jsr166e/ConcurrentHashMapV8.java +19 -10
  9. data/ext/org/jruby/ext/thread_safe/jsr166e/LongAdder.java +1 -2
  10. data/ext/org/jruby/ext/thread_safe/jsr166e/Striped64.java +1 -1
  11. data/ext/org/jruby/ext/thread_safe/jsr166e/nounsafe/ConcurrentHashMapV8.java +3788 -0
  12. data/ext/org/jruby/ext/thread_safe/jsr166e/nounsafe/LongAdder.java +204 -0
  13. data/ext/org/jruby/ext/thread_safe/jsr166e/nounsafe/Striped64.java +291 -0
  14. data/ext/org/jruby/ext/thread_safe/jsr166y/ThreadLocalRandom.java +1 -1
  15. data/ext/thread_safe/JrubyCacheBackendService.java +2 -2
  16. data/lib/thread_safe.rb +1 -1
  17. data/lib/thread_safe/atomic_reference_cache_backend.rb +1 -1
  18. data/lib/thread_safe/cache.rb +6 -3
  19. data/lib/thread_safe/mri_cache_backend.rb +2 -2
  20. data/lib/thread_safe/non_concurrent_cache_backend.rb +1 -1
  21. data/lib/thread_safe/synchronized_cache_backend.rb +1 -1
  22. data/lib/thread_safe/synchronized_delegator.rb +36 -19
  23. data/lib/thread_safe/util.rb +1 -1
  24. data/lib/thread_safe/util/adder.rb +1 -1
  25. data/lib/thread_safe/util/atomic_reference.rb +1 -1
  26. data/lib/thread_safe/util/cheap_lockable.rb +1 -1
  27. data/lib/thread_safe/util/power_of_two_tuple.rb +1 -1
  28. data/lib/thread_safe/util/striped64.rb +1 -1
  29. data/lib/thread_safe/util/volatile.rb +1 -1
  30. data/lib/thread_safe/util/volatile_tuple.rb +1 -1
  31. data/lib/thread_safe/util/xor_shift_random.rb +1 -1
  32. data/lib/thread_safe/version.rb +1 -1
  33. data/test/src/thread_safe/SecurityManager.java +21 -0
  34. data/test/test_array.rb +1 -1
  35. data/test/test_cache.rb +27 -10
  36. data/test/test_cache_loops.rb +377 -376
  37. data/test/test_hash.rb +1 -2
  38. data/test/test_helper.rb +33 -3
  39. data/test/test_synchronized_delegator.rb +67 -17
  40. data/thread_safe.gemspec +6 -3
  41. metadata +36 -10
@@ -9,7 +9,6 @@ class TestHash < Test::Unit::TestCase
9
9
  Thread.new do
10
10
  1000.times do |j|
11
11
  hsh[i*1000+j] = i
12
- hsh.each {|k,v| k + v}
13
12
  hsh[i*1000+j]
14
13
  hsh.delete(i*1000+j)
15
14
  end
@@ -17,4 +16,4 @@ class TestHash < Test::Unit::TestCase
17
16
  end.map(&:join)
18
17
  end
19
18
  end
20
- end
19
+ end
@@ -1,5 +1,31 @@
1
1
  require 'thread'
2
2
 
3
+ if defined?(JRUBY_VERSION) && ENV['TEST_NO_UNSAFE']
4
+ # to be used like this: rake test TEST_NO_UNSAFE=true
5
+ load 'test/package.jar'
6
+ java_import 'thread_safe.SecurityManager'
7
+ manager = SecurityManager.new
8
+
9
+ # Prevent accessing internal classes
10
+ manager.deny java.lang.RuntimePermission.new("accessClassInPackage.sun.misc")
11
+ java.lang.System.setSecurityManager manager
12
+
13
+ class TestNoUnsafe < Test::Unit::TestCase
14
+ def test_security_manager_is_used
15
+ begin
16
+ java_import 'sun.misc.Unsafe'
17
+ flunk
18
+ rescue SecurityError
19
+ end
20
+ end
21
+
22
+ def test_no_unsafe_version_of_chmv8_is_used
23
+ require 'thread_safe/jruby_cache_backend' # make sure the jar has been loaded
24
+ assert !Java::OrgJrubyExtThread_safe::JRubyCacheBackendLibrary::JRubyCacheBackend::CAN_USE_UNSAFE_CHM
25
+ end
26
+ end
27
+ end
28
+
3
29
  module ThreadSafe
4
30
  module Test
5
31
  class Latch
@@ -66,8 +92,12 @@ module ThreadSafe
66
92
 
67
93
  HASH_COLLISION_CLASSES = [HashCollisionKey, HashCollisionKey2, HashCollisionKeyNoCompare, HashCollisionKey4]
68
94
 
69
- def self.HashCollisionKey(key)
70
- HASH_COLLISION_CLASSES[rand(4)].new(key)
95
+ def self.HashCollisionKey(key, hash = key.hash % 3)
96
+ HASH_COLLISION_CLASSES[rand(4)].new(key, hash)
97
+ end
98
+
99
+ class HashCollisionKeyNonComparable < HashCollisionKey
100
+ undef <=>
71
101
  end
72
102
  end
73
- end
103
+ end
@@ -2,41 +2,91 @@ require 'test/unit'
2
2
  require 'thread_safe/synchronized_delegator.rb'
3
3
 
4
4
  class TestSynchronizedDelegator < Test::Unit::TestCase
5
+ def setup
6
+ @old_abort = Thread.abort_on_exception
7
+ Thread.abort_on_exception = true
8
+ end
9
+
10
+ def teardown
11
+ Thread.abort_on_exception = @old_abort
12
+ end
13
+
5
14
  def test_wraps_array
6
- ary = []
7
- sync_ary = SynchronizedDelegator.new(ary)
15
+ sync_array = SynchronizedDelegator.new(array = [])
8
16
 
9
- ary << 1
10
- assert_equal 1, sync_ary[0]
17
+ array << 1
18
+ assert_equal 1, sync_array[0]
19
+
20
+ sync_array << 2
21
+ assert_equal 2, array[1]
11
22
  end
12
23
 
13
24
  def test_synchronizes_access
14
- ary = []
15
- sync_ary = SynchronizedDelegator.new(ary)
25
+ t1_continue, t2_continue = false, false
16
26
 
17
- t1_continue = false
18
- t2_continue = false
27
+ hash = Hash.new do |hash, key|
28
+ t2_continue = true
29
+ unless hash.find { |e| e[1] == key.to_s } # just to do something
30
+ hash[key] = key.to_s
31
+ Thread.pass until t1_continue
32
+ end
33
+ end
34
+ sync_hash = SynchronizedDelegator.new(hash)
35
+ sync_hash[1] = 'egy'
19
36
 
20
37
  t1 = Thread.new do
21
- sync_ary << 1
22
- sync_ary.each do
38
+ sync_hash[2] = 'dva'
39
+ sync_hash[3] # triggers t2_continue
40
+ end
41
+
42
+ t2 = Thread.new do
43
+ Thread.pass until t2_continue
44
+ sync_hash[4] = '42'
45
+ end
46
+
47
+ sleep(0.05) # sleep some to allow threads to boot
48
+
49
+ until t2.status == 'sleep' do
50
+ Thread.pass
51
+ end
52
+
53
+ assert_equal 3, hash.keys.size
54
+
55
+ t1_continue = true
56
+ t1.join; t2.join
57
+
58
+ assert_equal 4, sync_hash.size
59
+ end
60
+
61
+ def test_synchronizes_access_with_block
62
+ t1_continue, t2_continue = false, false
63
+
64
+ sync_array = SynchronizedDelegator.new(array = [])
65
+
66
+ t1 = Thread.new do
67
+ sync_array << 1
68
+ sync_array.each do
23
69
  t2_continue = true
24
70
  Thread.pass until t1_continue
25
71
  end
26
72
  end
27
73
 
28
74
  t2 = Thread.new do
75
+ # sleep(0.01)
29
76
  Thread.pass until t2_continue
30
- sync_ary << 2
77
+ sync_array << 2
31
78
  end
32
-
33
- Thread.pass until t2.status == 'sleep'
34
- assert_equal 1, ary.size
79
+
80
+ until t2.status == 'sleep' || t2.status == false do
81
+ Thread.pass
82
+ end
83
+
84
+ assert_equal 1, array.size
35
85
 
36
86
  t1_continue = true
37
- t1.join
38
- t2.join
87
+ t1.join; t2.join
39
88
 
40
- assert_equal 2, sync_ary.size
89
+ assert_equal [1, 2], array
41
90
  end
91
+
42
92
  end
@@ -1,5 +1,6 @@
1
1
  # -*- encoding: utf-8 -*-
2
- require File.expand_path('../lib/thread_safe/version', __FILE__)
2
+ $:.push File.expand_path('../lib', __FILE__) unless $:.include?('lib')
3
+ require 'thread_safe/version'
3
4
 
4
5
  Gem::Specification.new do |gem|
5
6
  gem.authors = ["Charles Oliver Nutter", "thedarkone"]
@@ -8,7 +9,8 @@ Gem::Specification.new do |gem|
8
9
  gem.summary = %q{A collection of data structures and utilities to make thread-safe programming in Ruby easier}
9
10
  gem.homepage = "https://github.com/headius/thread_safe"
10
11
 
11
- gem.files = `git ls-files`.split($\) | Dir['{lib,examples,test}/**/*.jar']
12
+ gem.files = `git ls-files`.split($\)
13
+ gem.files += ['lib/thread_safe/jruby_cache_backend.jar'] if defined?(JRUBY_VERSION)
12
14
  gem.platform = 'java' if defined?(JRUBY_VERSION)
13
15
  gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
14
16
  gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
@@ -17,5 +19,6 @@ Gem::Specification.new do |gem|
17
19
  gem.version = Threadsafe::VERSION
18
20
  gem.license = "Apache-2.0"
19
21
 
20
- gem.add_dependency 'atomic'
22
+ gem.add_dependency 'atomic', ['>= 1.1.7', '< 2']
23
+ gem.add_development_dependency 'rake'
21
24
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: thread_safe
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.3
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Charles Oliver Nutter
@@ -9,20 +9,40 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-09-10 00:00:00.000000000 Z
12
+ date: 2014-02-26 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: atomic
16
16
  requirement: !ruby/object:Gem::Requirement
17
17
  requirements:
18
- - - '>='
18
+ - - ">="
19
19
  - !ruby/object:Gem::Version
20
- version: '0'
20
+ version: 1.1.7
21
+ - - "<"
22
+ - !ruby/object:Gem::Version
23
+ version: '2'
21
24
  type: :runtime
22
25
  prerelease: false
23
26
  version_requirements: !ruby/object:Gem::Requirement
24
27
  requirements:
25
- - - '>='
28
+ - - ">="
29
+ - !ruby/object:Gem::Version
30
+ version: 1.1.7
31
+ - - "<"
32
+ - !ruby/object:Gem::Version
33
+ version: '2'
34
+ - !ruby/object:Gem::Dependency
35
+ name: rake
36
+ requirement: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ type: :development
42
+ prerelease: false
43
+ version_requirements: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
26
46
  - !ruby/object:Gem::Version
27
47
  version: '0'
28
48
  description: Thread-safe collections and utilities for Ruby
@@ -33,16 +53,21 @@ executables: []
33
53
  extensions: []
34
54
  extra_rdoc_files: []
35
55
  files:
36
- - .gitignore
56
+ - ".gitignore"
57
+ - ".travis.yml"
37
58
  - Gemfile
38
59
  - LICENSE
39
60
  - README.md
40
61
  - Rakefile
41
62
  - examples/bench_cache.rb
42
63
  - ext/org/jruby/ext/thread_safe/JRubyCacheBackendLibrary.java
64
+ - ext/org/jruby/ext/thread_safe/jsr166e/ConcurrentHashMap.java
43
65
  - ext/org/jruby/ext/thread_safe/jsr166e/ConcurrentHashMapV8.java
44
66
  - ext/org/jruby/ext/thread_safe/jsr166e/LongAdder.java
45
67
  - ext/org/jruby/ext/thread_safe/jsr166e/Striped64.java
68
+ - ext/org/jruby/ext/thread_safe/jsr166e/nounsafe/ConcurrentHashMapV8.java
69
+ - ext/org/jruby/ext/thread_safe/jsr166e/nounsafe/LongAdder.java
70
+ - ext/org/jruby/ext/thread_safe/jsr166e/nounsafe/Striped64.java
46
71
  - ext/org/jruby/ext/thread_safe/jsr166y/ThreadLocalRandom.java
47
72
  - ext/thread_safe/JrubyCacheBackendService.java
48
73
  - lib/thread_safe.rb
@@ -62,6 +87,7 @@ files:
62
87
  - lib/thread_safe/util/volatile_tuple.rb
63
88
  - lib/thread_safe/util/xor_shift_random.rb
64
89
  - lib/thread_safe/version.rb
90
+ - test/src/thread_safe/SecurityManager.java
65
91
  - test/test_array.rb
66
92
  - test/test_cache.rb
67
93
  - test/test_cache_loops.rb
@@ -69,7 +95,6 @@ files:
69
95
  - test/test_helper.rb
70
96
  - test/test_synchronized_delegator.rb
71
97
  - thread_safe.gemspec
72
- - lib/thread_safe/jruby_cache_backend.jar
73
98
  homepage: https://github.com/headius/thread_safe
74
99
  licenses:
75
100
  - Apache-2.0
@@ -80,22 +105,23 @@ require_paths:
80
105
  - lib
81
106
  required_ruby_version: !ruby/object:Gem::Requirement
82
107
  requirements:
83
- - - '>='
108
+ - - ">="
84
109
  - !ruby/object:Gem::Version
85
110
  version: '0'
86
111
  required_rubygems_version: !ruby/object:Gem::Requirement
87
112
  requirements:
88
- - - '>='
113
+ - - ">="
89
114
  - !ruby/object:Gem::Version
90
115
  version: '0'
91
116
  requirements: []
92
117
  rubyforge_project:
93
- rubygems_version: 2.1.0
118
+ rubygems_version: 2.2.0
94
119
  signing_key:
95
120
  specification_version: 4
96
121
  summary: A collection of data structures and utilities to make thread-safe programming
97
122
  in Ruby easier
98
123
  test_files:
124
+ - test/src/thread_safe/SecurityManager.java
99
125
  - test/test_array.rb
100
126
  - test/test_cache.rb
101
127
  - test/test_cache_loops.rb