thread_safe 0.2.0 → 0.3.1

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: ca3399bd6ea44fe01680773e7b50bd0e7ba83180
4
- data.tar.gz: 5538a41397738daa6a068386fb75c957b68554f9
3
+ metadata.gz: becd0122b50b5237811fa86271f7d33724680011
4
+ data.tar.gz: 3111e146b92de7b07e7b052b3dd126aaad1aca2c
5
5
  SHA512:
6
- metadata.gz: 4de26c2ec5e34448f165a1e7eb6893025d969c41be6f5bbbe02e158c31151871de7c71d9cf5ee8f9d7effc48c871a74b178c030fede73061a6f9c9273a220f9c
7
- data.tar.gz: 2f0bddce90244d49e4d0443ffe9d739f8f1732021875e5707c9224add8aac54cce31472accb0fc8471273c12c755cc56e797f5b0087160ba203e8caf3f72387c
6
+ metadata.gz: ae11d6069603a1f4a6ae9ce62347629b22b2841c4008f248fd05b5c5fc2449913fbc0554919f4615e0abd55fdb903a42eee1520fbc723e17618e7b6419933559
7
+ data.tar.gz: 8c80390a923556d2627d89af464e51ddae6ac9b5c44a485c6c6c0ad804b01aeed631680a7ab23c63e46293d8649978eceb5dd40cc6218d1f101597baf50b6ee1
data/.gitignore CHANGED
@@ -19,3 +19,4 @@ test/version_tmp
19
19
  tmp
20
20
  .DS_Store
21
21
  *.swp
22
+ test/package.jar
data/README.md CHANGED
@@ -28,14 +28,22 @@ sh = ThreadSafe::Hash.new # supports standard Hash.new forms
28
28
  ```
29
29
 
30
30
  `ThreadSafe::Cache` also exists, as a hash-like object, and should have
31
- much better performance characteristics under concurrency than
31
+ much better performance characteristics esp. under high concurrency than
32
32
  `ThreadSafe::Hash`. However, `ThreadSafe::Cache` is not strictly semantically
33
- equivalent to ruby Hash -- for instance, it does not neccesarily ordered by
34
- insertion time as Hash is. For most uses it should do fine though, and we
35
- recommend you consider `ThreadSafe::Cache` instead of `ThreadSafe::Hash` for your
36
- concurrency-safe hash needs.
33
+ equivalent to a ruby `Hash` -- for instance, it does not necessarily retain
34
+ ordering by insertion time as `Hash` does. For most uses it should do fine
35
+ though, and we recommend you consider `ThreadSafe::Cache` instead of
36
+ `ThreadSafe::Hash` for your concurrency-safe hash needs. It understands some
37
+ options when created (depending on your ruby platform) that control some of the
38
+ internals - when unsure just leave them out:
37
39
 
38
40
 
41
+ ```ruby
42
+ require 'thread_safe'
43
+
44
+ cache = ThreadSafe::Cache.new
45
+ ```
46
+
39
47
  ## Contributing
40
48
 
41
49
  1. Fork it
@@ -178,11 +178,17 @@ public class JRubyCacheBackendLibrary implements Library {
178
178
  return getRuntime().newBoolean(map.replace(key, oldValue, newValue));
179
179
  }
180
180
 
181
- @JRubyMethod(name = {"key?"}, required = 1)
181
+ @JRubyMethod(name = "key?", required = 1)
182
182
  public RubyBoolean has_key_p(IRubyObject key) {
183
183
  return map.containsKey(key) ? getRuntime().getTrue() : getRuntime().getFalse();
184
184
  }
185
185
 
186
+ @JRubyMethod
187
+ public IRubyObject key(IRubyObject value) {
188
+ final IRubyObject key = map.findKey(value);
189
+ return key == null ? getRuntime().getNil() : key;
190
+ }
191
+
186
192
  @JRubyMethod
187
193
  public IRubyObject replace_if_exists(IRubyObject key, IRubyObject value) {
188
194
  IRubyObject result = map.replace(key, value);
@@ -25,4 +25,7 @@ public interface ConcurrentHashMap<K, V> {
25
25
  public Set<Map.Entry<K,V>> entrySet();
26
26
  public int size();
27
27
  public V getValueOrDefault(Object key, V defaultValue);
28
+
29
+ public boolean containsValue(V value);
30
+ public K findKey(V value);
28
31
  }
@@ -2430,8 +2430,8 @@ public class ConcurrentHashMapV8<K, V>
2430
2430
  @SuppressWarnings("serial") static class Traverser<K,V,R> {
2431
2431
  final ConcurrentHashMapV8<K, V> map;
2432
2432
  Node next; // the next entry to use
2433
- Object nextKey; // cached key field of next
2434
- Object nextVal; // cached val field of next
2433
+ K nextKey; // cached key field of next
2434
+ V nextVal; // cached val field of next
2435
2435
  Node[] tab; // current table; updated if resized
2436
2436
  int index; // index of bin to use next
2437
2437
  int baseIndex; // current index of initial table
@@ -2461,9 +2461,9 @@ public class ConcurrentHashMapV8<K, V>
2461
2461
  * Advances next; returns nextVal or null if terminated.
2462
2462
  * See above for explanation.
2463
2463
  */
2464
- final Object advance() {
2464
+ final V advance() {
2465
2465
  Node e = next;
2466
- Object ev = null;
2466
+ V ev = null;
2467
2467
  outer: do {
2468
2468
  if (e != null) // advance past used/skipped node
2469
2469
  e = e.next;
@@ -2489,8 +2489,8 @@ public class ConcurrentHashMapV8<K, V>
2489
2489
  } // visit upper slots if present
2490
2490
  index = (i += baseSize) < n ? i : (baseIndex = b + 1);
2491
2491
  }
2492
- nextKey = e.key;
2493
- } while ((ev = e.val) == null); // skip deleted or special nodes
2492
+ nextKey = (K) e.key;
2493
+ } while ((ev = (V) e.val) == null); // skip deleted or special nodes
2494
2494
  next = e;
2495
2495
  return nextVal = ev;
2496
2496
  }
@@ -2730,6 +2730,18 @@ public class ConcurrentHashMapV8<K, V>
2730
2730
  return false;
2731
2731
  }
2732
2732
 
2733
+ public K findKey(Object value) {
2734
+ if (value == null)
2735
+ throw new NullPointerException();
2736
+ Object v;
2737
+ Traverser<K,V,Object> it = new Traverser<K,V,Object>(this);
2738
+ while ((v = it.advance()) != null) {
2739
+ if (v == value || value.equals(v))
2740
+ return it.nextKey;
2741
+ }
2742
+ return null;
2743
+ }
2744
+
2733
2745
  /**
2734
2746
  * Legacy method testing if some key maps into the specified value
2735
2747
  * in this table. This method is identical in functionality to
@@ -2422,8 +2422,8 @@ public class ConcurrentHashMapV8<K, V>
2422
2422
  @SuppressWarnings("serial") static class Traverser<K,V,R> {
2423
2423
  final ConcurrentHashMapV8<K, V> map;
2424
2424
  Node next; // the next entry to use
2425
- Object nextKey; // cached key field of next
2426
- Object nextVal; // cached val field of next
2425
+ K nextKey; // cached key field of next
2426
+ V nextVal; // cached val field of next
2427
2427
  AtomicReferenceArray<Node> tab; // current table; updated if resized
2428
2428
  int index; // index of bin to use next
2429
2429
  int baseIndex; // current index of initial table
@@ -2453,9 +2453,9 @@ public class ConcurrentHashMapV8<K, V>
2453
2453
  * Advances next; returns nextVal or null if terminated.
2454
2454
  * See above for explanation.
2455
2455
  */
2456
- final Object advance() {
2456
+ final V advance() {
2457
2457
  Node e = next;
2458
- Object ev = null;
2458
+ V ev = null;
2459
2459
  outer: do {
2460
2460
  if (e != null) // advance past used/skipped node
2461
2461
  e = e.next;
@@ -2481,8 +2481,8 @@ public class ConcurrentHashMapV8<K, V>
2481
2481
  } // visit upper slots if present
2482
2482
  index = (i += baseSize) < n ? i : (baseIndex = b + 1);
2483
2483
  }
2484
- nextKey = e.key;
2485
- } while ((ev = e.val) == null); // skip deleted or special nodes
2484
+ nextKey = (K) e.key;
2485
+ } while ((ev = (V) e.val) == null); // skip deleted or special nodes
2486
2486
  next = e;
2487
2487
  return nextVal = ev;
2488
2488
  }
@@ -2722,6 +2722,18 @@ public class ConcurrentHashMapV8<K, V>
2722
2722
  return false;
2723
2723
  }
2724
2724
 
2725
+ public K findKey(Object value) {
2726
+ if (value == null)
2727
+ throw new NullPointerException();
2728
+ Object v;
2729
+ Traverser<K,V,Object> it = new Traverser<K,V,Object>(this);
2730
+ while ((v = it.advance()) != null) {
2731
+ if (v == value || value.equals(v))
2732
+ return it.nextKey;
2733
+ }
2734
+ return null;
2735
+ }
2736
+
2725
2737
  /**
2726
2738
  * Legacy method testing if some key maps into the specified value
2727
2739
  * in this table. This method is identical in functionality to
@@ -95,6 +95,12 @@ module ThreadSafe
95
95
  each_pair {|k, v| yield v}
96
96
  end unless method_defined?(:each_value)
97
97
 
98
+ def key(value)
99
+ each_pair {|k, v| return k if v == value}
100
+ nil
101
+ end unless method_defined?(:key)
102
+ alias_method :index, :key if RUBY_VERSION < '1.9'
103
+
98
104
  def empty?
99
105
  each_pair {|k, v| return false}
100
106
  true
@@ -1,3 +1,21 @@
1
+ module ThreadSafe
2
+ VERSION = "0.3.1"
3
+ end
4
+
5
+ # NOTE: <= 0.2.0 used Threadsafe::VERSION
6
+ # @private
1
7
  module Threadsafe
2
- VERSION = "0.2.0"
8
+
9
+ # @private
10
+ def self.const_missing(name)
11
+ name = name.to_sym
12
+ if ThreadSafe.const_defined?(name)
13
+ warn "[DEPRECATION] `Threadsafe::#{name}' is deprecated, use `ThreadSafe::#{name}' instead."
14
+ ThreadSafe.const_get(name)
15
+ else
16
+ warn "[DEPRECATION] the `Threadsafe' module is deprecated, please use `ThreadSafe` instead."
17
+ super
18
+ end
19
+ end
20
+
3
21
  end
data/test/test_cache.rb CHANGED
@@ -371,6 +371,16 @@ class TestCache < Test::Unit::TestCase
371
371
  end
372
372
 
373
373
  def test_key
374
+ with_or_without_default_proc do
375
+ assert_equal nil, @cache.key(1)
376
+ @cache[:a] = 1
377
+ assert_equal :a, @cache.key(1)
378
+ assert_equal nil, @cache.key(0)
379
+ assert_equal :a, @cache.index(1) if RUBY_VERSION =~ /1\.8/
380
+ end
381
+ end
382
+
383
+ def test_key?
374
384
  with_or_without_default_proc do
375
385
  assert_equal false, @cache.key?(:a)
376
386
  @cache[:a] = 1
@@ -378,7 +388,7 @@ class TestCache < Test::Unit::TestCase
378
388
  end
379
389
  end
380
390
 
381
- def test_value
391
+ def test_value?
382
392
  with_or_without_default_proc do
383
393
  assert_equal false, @cache.value?(1)
384
394
  @cache[:a] = 1
data/thread_safe.gemspec CHANGED
@@ -16,7 +16,7 @@ Gem::Specification.new do |gem|
16
16
  gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
17
17
  gem.name = "thread_safe"
18
18
  gem.require_paths = ["lib"]
19
- gem.version = Threadsafe::VERSION
19
+ gem.version = ThreadSafe::VERSION
20
20
  gem.license = "Apache-2.0"
21
21
 
22
22
  gem.add_dependency 'atomic', ['>= 1.1.7', '< 2']
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.2.0
4
+ version: 0.3.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Charles Oliver Nutter
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2014-02-26 00:00:00.000000000 Z
12
+ date: 2014-03-21 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: atomic
@@ -115,7 +115,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
115
115
  version: '0'
116
116
  requirements: []
117
117
  rubyforge_project:
118
- rubygems_version: 2.2.0
118
+ rubygems_version: 2.2.2
119
119
  signing_key:
120
120
  specification_version: 4
121
121
  summary: A collection of data structures and utilities to make thread-safe programming
@@ -128,4 +128,3 @@ test_files:
128
128
  - test/test_hash.rb
129
129
  - test/test_helper.rb
130
130
  - test/test_synchronized_delegator.rb
131
- has_rdoc: