thread_safe 0.1.3 → 0.2.0

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