thread_safe 0.1.1-java

Sign up to get free protection for your applications and to get access to all the features.
Files changed (38) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +21 -0
  3. data/Gemfile +4 -0
  4. data/LICENSE +144 -0
  5. data/README.md +34 -0
  6. data/Rakefile +36 -0
  7. data/examples/bench_cache.rb +35 -0
  8. data/ext/org/jruby/ext/thread_safe/JRubyCacheBackendLibrary.java +200 -0
  9. data/ext/org/jruby/ext/thread_safe/jsr166e/ConcurrentHashMapV8.java +3842 -0
  10. data/ext/org/jruby/ext/thread_safe/jsr166e/LongAdder.java +204 -0
  11. data/ext/org/jruby/ext/thread_safe/jsr166e/Striped64.java +342 -0
  12. data/ext/org/jruby/ext/thread_safe/jsr166y/ThreadLocalRandom.java +199 -0
  13. data/ext/thread_safe/JrubyCacheBackendService.java +15 -0
  14. data/lib/thread_safe.rb +65 -0
  15. data/lib/thread_safe/atomic_reference_cache_backend.rb +922 -0
  16. data/lib/thread_safe/cache.rb +137 -0
  17. data/lib/thread_safe/mri_cache_backend.rb +62 -0
  18. data/lib/thread_safe/non_concurrent_cache_backend.rb +133 -0
  19. data/lib/thread_safe/synchronized_cache_backend.rb +76 -0
  20. data/lib/thread_safe/synchronized_delegator.rb +35 -0
  21. data/lib/thread_safe/util.rb +16 -0
  22. data/lib/thread_safe/util/adder.rb +59 -0
  23. data/lib/thread_safe/util/atomic_reference.rb +12 -0
  24. data/lib/thread_safe/util/cheap_lockable.rb +105 -0
  25. data/lib/thread_safe/util/power_of_two_tuple.rb +26 -0
  26. data/lib/thread_safe/util/striped64.rb +226 -0
  27. data/lib/thread_safe/util/volatile.rb +62 -0
  28. data/lib/thread_safe/util/volatile_tuple.rb +46 -0
  29. data/lib/thread_safe/util/xor_shift_random.rb +39 -0
  30. data/lib/thread_safe/version.rb +3 -0
  31. data/test/test_array.rb +20 -0
  32. data/test/test_cache.rb +792 -0
  33. data/test/test_cache_loops.rb +453 -0
  34. data/test/test_hash.rb +20 -0
  35. data/test/test_helper.rb +73 -0
  36. data/test/test_synchronized_delegator.rb +42 -0
  37. data/thread_safe.gemspec +21 -0
  38. metadata +100 -0
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: cf3a45ded3324dfded8db4f59ed37b82fcb91da5
4
+ data.tar.gz: 8cb64fa6a2ce0dee67f5aae452ae780d18d5817f
5
+ SHA512:
6
+ metadata.gz: a3ea40a7ad6256df359b64ea27a23dbd27174e05a068b615e4b67f221638a350fa8b32f6d04f3976025f3c571fb0e034299e3c5aaa7d150da13d0bb3b36e2994
7
+ data.tar.gz: c66f4c83ad5d9e174a077c3655623d8ea4f0829c85169c32658b2ebfb57d20a31c76664956d79fa64fff6c0b2b32f9e1786bb96798462adedfa7d069de79a02f
@@ -0,0 +1,21 @@
1
+ *.gem
2
+ *.rbc
3
+ .rbx/*
4
+ .bundle
5
+ .config
6
+ .yardoc
7
+ Gemfile.lock
8
+ InstalledFiles
9
+ _yardoc
10
+ coverage
11
+ doc/
12
+ lib/bundler/man
13
+ lib/thread_safe/jruby_cache_backend.jar
14
+ pkg
15
+ rdoc
16
+ spec/reports
17
+ test/tmp
18
+ test/version_tmp
19
+ tmp
20
+ .DS_Store
21
+ *.swp
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in thread_safe.gemspec
4
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,144 @@
1
+ Apache License
2
+
3
+ Version 2.0, January 2004
4
+
5
+ http://www.apache.org/licenses/
6
+
7
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
8
+
9
+ 1. Definitions.
10
+
11
+ "License" shall mean the terms and conditions for use, reproduction, and distribution as
12
+ defined by Sections 1 through 9 of this document.
13
+
14
+ "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that
15
+ is granting the License.
16
+
17
+ "Legal Entity" shall mean the union of the acting entity and all other entities that
18
+ control, are controlled by, or are under common control with that entity. For the purposes
19
+ of this definition, "control" means (i) the power, direct or indirect, to cause the
20
+ direction or management of such entity, whether by contract or otherwise, or (ii) ownership
21
+ of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of
22
+ such entity.
23
+
24
+ "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by
25
+ this License.
26
+
27
+ "Source" form shall mean the preferred form for making modifications, including but not
28
+ limited to software source code, documentation source, and configuration files.
29
+
30
+ "Object" form shall mean any form resulting from mechanical transformation or translation of
31
+ a Source form, including but not limited to compiled object code, generated documentation,
32
+ and conversions to other media types.
33
+
34
+ "Work" shall mean the work of authorship, whether in Source or Object form, made available
35
+ under the License, as indicated by a copyright notice that is included in or attached to the
36
+ work (an example is provided in the Appendix below).
37
+
38
+ "Derivative Works" shall mean any work, whether in Source or Object form, that is based on
39
+ (or derived from) the Work and for which the editorial revisions, annotations, elaborations,
40
+ or other modifications represent, as a whole, an original work of authorship. For the
41
+ purposes of this License, Derivative Works shall not include works that remain separable
42
+ from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works
43
+ thereof.
44
+
45
+ "Contribution" shall mean any work of authorship, including the original version of the Work
46
+ and any modifications or additions to that Work or Derivative Works thereof, that is
47
+ intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by
48
+ an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the
49
+ purposes of this definition, "submitted" means any form of electronic, verbal, or written
50
+ communication sent to the Licensor or its representatives, including but not limited to
51
+ communication on electronic mailing lists, source code control systems, and issue tracking
52
+ systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and
53
+ improving the Work, but excluding communication that is conspicuously marked or otherwise
54
+ designated in writing by the copyright owner as "Not a Contribution."
55
+
56
+ "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a
57
+ Contribution has been received by Licensor and subsequently incorporated within the Work.
58
+
59
+ 2. Grant of Copyright License. Subject to the terms and conditions of this License, each
60
+ Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge,
61
+ royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of,
62
+ publicly display, publicly perform, sublicense, and distribute the Work and such Derivative
63
+ Works in Source or Object form.
64
+
65
+ 3. Grant of Patent License. Subject to the terms and conditions of this License, each
66
+ Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge,
67
+ royalty-free, irrevocable (except as stated in this section) patent license to make, have
68
+ made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license
69
+ applies only to those patent claims licensable by such Contributor that are necessarily
70
+ infringed by their Contribution(s) alone or by combination of their Contribution(s) with the
71
+ Work to which such Contribution(s) was submitted. If You institute patent litigation against
72
+ any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or
73
+ a Contribution incorporated within the Work constitutes direct or contributory patent
74
+ infringement, then any patent licenses granted to You under this License for that Work shall
75
+ terminate as of the date such litigation is filed.
76
+
77
+ 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works
78
+ thereof in any medium, with or without modifications, and in Source or Object form, provided
79
+ that You meet the following conditions:
80
+
81
+ You must give any other recipients of the Work or Derivative Works a copy of this License;
82
+ and
83
+
84
+ You must cause any modified files to carry prominent notices stating that You changed the
85
+ files; and
86
+
87
+ You must retain, in the Source form of any Derivative Works that You distribute, all
88
+ copyright, patent, trademark, and attribution notices from the Source form of the Work,
89
+ excluding those notices that do not pertain to any part of the Derivative Works; and
90
+
91
+ If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative
92
+ Works that You distribute must include a readable copy of the attribution notices contained
93
+ within such NOTICE file, excluding those notices that do not pertain to any part of the
94
+ Derivative Works, in at least one of the following places: within a NOTICE text file
95
+ distributed as part of the Derivative Works; within the Source form or documentation, if
96
+ provided along with the Derivative Works; or, within a display generated by the Derivative
97
+ Works, if and wherever such third-party notices normally appear. The contents of the NOTICE
98
+ file are for informational purposes only and do not modify the License. You may add Your own
99
+ attribution notices within Derivative Works that You distribute, alongside or as an addendum
100
+ to the NOTICE text from the Work, provided that such additional attribution notices cannot
101
+ be construed as modifying the License. You may add Your own copyright statement to Your
102
+ modifications and may provide additional or different license terms and conditions for use,
103
+ reproduction, or distribution of Your modifications, or for any such Derivative Works as a
104
+ whole, provided Your use, reproduction, and distribution of the Work otherwise complies with
105
+ the conditions stated in this License.
106
+
107
+ 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution
108
+ intentionally submitted for inclusion in the Work by You to the Licensor shall be under the
109
+ terms and conditions of this License, without any additional terms or conditions.
110
+ Notwithstanding the above, nothing herein shall supersede or modify the terms of any
111
+ separate license agreement you may have executed with Licensor regarding such Contributions.
112
+
113
+ 6. Trademarks. This License does not grant permission to use the trade names, trademarks,
114
+ service marks, or product names of the Licensor, except as required for reasonable and
115
+ customary use in describing the origin of the Work and reproducing the content of the NOTICE
116
+ file.
117
+
118
+ 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing,
119
+ Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS"
120
+ BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including,
121
+ without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT,
122
+ MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for
123
+ determining the appropriateness of using or redistributing the Work and assume any risks
124
+ associated with Your exercise of permissions under this License.
125
+
126
+ 8. Limitation of Liability. In no event and under no legal theory, whether in tort
127
+ (including negligence), contract, or otherwise, unless required by applicable law (such as
128
+ deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be
129
+ liable to You for damages, including any direct, indirect, special, incidental, or
130
+ consequential damages of any character arising as a result of this License or out of the use
131
+ or inability to use the Work (including but not limited to damages for loss of goodwill,
132
+ work stoppage, computer failure or malfunction, or any and all other commercial damages or
133
+ losses), even if such Contributor has been advised of the possibility of such damages.
134
+
135
+ 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative
136
+ Works thereof, You may choose to offer, and charge a fee for, acceptance of support,
137
+ warranty, indemnity, or other liability obligations and/or rights consistent with this
138
+ License. However, in accepting such obligations, You may act only on Your own behalf and on
139
+ Your sole responsibility, not on behalf of any other Contributor, and only if You agree to
140
+ indemnify, defend, and hold each Contributor harmless for any liability incurred by, or
141
+ claims asserted against, such Contributor by reason of your accepting any such warranty or
142
+ additional liability.
143
+
144
+ END OF TERMS AND CONDITIONS
@@ -0,0 +1,34 @@
1
+ # Threadsafe
2
+
3
+ A collection of thread-safe versions of common core Ruby classes.
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'thread_safe'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install thread_safe
18
+
19
+ ## Usage
20
+
21
+ ```
22
+ require 'thread_safe'
23
+
24
+ sa = ThreadSafe::Array.new # supports standard Array.new forms
25
+ sh = ThreadSafe::Hash.new # supports standard Hash.new forms
26
+ ```
27
+
28
+ ## Contributing
29
+
30
+ 1. Fork it
31
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
32
+ 3. Commit your changes (`git commit -am 'Added some feature'`)
33
+ 4. Push to the branch (`git push origin my-new-feature`)
34
+ 5. Create new Pull Request
@@ -0,0 +1,36 @@
1
+ #!/usr/bin/env rake
2
+ require "bundler/gem_tasks"
3
+ require 'rake/testtask'
4
+
5
+ task :default => :test
6
+
7
+ Rake::TestTask.new :test do |t|
8
+ t.libs << "lib"
9
+ t.test_files = FileList["test/**/*.rb"]
10
+ end
11
+
12
+ if defined?(JRUBY_VERSION)
13
+ require 'ant'
14
+
15
+ directory "pkg/classes"
16
+
17
+ desc "Clean up build artifacts"
18
+ task :clean do
19
+ rm_rf "pkg/classes"
20
+ rm_rf "lib/thread_safe/jruby_cache_backend.jar"
21
+ end
22
+
23
+ desc "Compile the extension"
24
+ task :compile => "pkg/classes" do |t|
25
+ ant.javac :srcdir => "ext", :destdir => t.prerequisites.first,
26
+ :source => "1.5", :target => "1.5", :debug => true,
27
+ :classpath => "${java.class.path}:${sun.boot.class.path}"
28
+ end
29
+
30
+ desc "Build the jar"
31
+ task :jar => :compile do
32
+ ant.jar :basedir => "pkg/classes", :destfile => "lib/thread_safe/jruby_cache_backend.jar", :includes => "**/*.class"
33
+ end
34
+
35
+ task :package => :jar
36
+ end
@@ -0,0 +1,35 @@
1
+ #!/usr/bin/env ruby -wKU
2
+
3
+ require "benchmark"
4
+ require "thread_safe"
5
+
6
+ hash = {}
7
+ cache = ThreadSafe::Cache.new
8
+
9
+ ENTRIES = 10_000
10
+
11
+ ENTRIES.times do |i|
12
+ hash[i] = i
13
+ cache[i] = i
14
+ end
15
+
16
+ TESTS = 40_000_000
17
+ Benchmark.bmbm do |results|
18
+ key = rand(10_000)
19
+
20
+ results.report('Hash#[]') do
21
+ TESTS.times { hash[key] }
22
+ end
23
+
24
+ results.report('Cache#[]') do
25
+ TESTS.times { cache[key] }
26
+ end
27
+
28
+ results.report('Hash#each_pair') do
29
+ (TESTS / ENTRIES).times { hash.each_pair {|k,v| v} }
30
+ end
31
+
32
+ results.report('Cache#each_pair') do
33
+ (TESTS / ENTRIES).times { cache.each_pair {|k,v| v} }
34
+ end
35
+ end
@@ -0,0 +1,200 @@
1
+ package org.jruby.ext.thread_safe;
2
+
3
+ import org.jruby.*;
4
+ import org.jruby.anno.JRubyClass;
5
+ import org.jruby.anno.JRubyMethod;
6
+ import org.jruby.ext.thread_safe.jsr166e.ConcurrentHashMapV8;
7
+ import org.jruby.runtime.Block;
8
+ import org.jruby.runtime.ObjectAllocator;
9
+ import org.jruby.runtime.ThreadContext;
10
+ import org.jruby.runtime.builtin.IRubyObject;
11
+ import org.jruby.runtime.load.Library;
12
+
13
+ import java.io.IOException;
14
+ import java.util.Map;
15
+
16
+ import static org.jruby.runtime.Visibility.PRIVATE;
17
+
18
+ /**
19
+ * Native Java implementation to avoid the JI overhead.
20
+ *
21
+ * @author thedarkone
22
+ */
23
+ public class JRubyCacheBackendLibrary implements Library {
24
+ public void load(Ruby runtime, boolean wrap) throws IOException {
25
+ RubyClass jrubyRefClass = runtime.defineClassUnder("JRubyCacheBackend", runtime.getObject(), BACKEND_ALLOCATOR, runtime.getModule("ThreadSafe"));
26
+ jrubyRefClass.setAllocator(BACKEND_ALLOCATOR);
27
+ jrubyRefClass.defineAnnotatedMethods(JRubyCacheBackend.class);
28
+ }
29
+
30
+ private static final ObjectAllocator BACKEND_ALLOCATOR = new ObjectAllocator() {
31
+ public IRubyObject allocate(Ruby runtime, RubyClass klazz) {
32
+ return new JRubyCacheBackend(runtime, klazz);
33
+ }
34
+ };
35
+
36
+ @JRubyClass(name="JRubyCacheBackend", parent="Object")
37
+ public static class JRubyCacheBackend extends RubyObject {
38
+ // Defaults used by the CHM
39
+ static final int DEFAULT_INITIAL_CAPACITY = 16;
40
+ static final float DEFAULT_LOAD_FACTOR = 0.75f;
41
+
42
+ private ConcurrentHashMapV8<IRubyObject, IRubyObject> map;
43
+
44
+ public JRubyCacheBackend(Ruby runtime, RubyClass klass) {
45
+ super(runtime, klass);
46
+ }
47
+
48
+ @JRubyMethod
49
+ public IRubyObject initialize(ThreadContext context) {
50
+ map = new ConcurrentHashMapV8<IRubyObject, IRubyObject>();
51
+ return context.getRuntime().getNil();
52
+ }
53
+
54
+ @JRubyMethod
55
+ public IRubyObject initialize(ThreadContext context, IRubyObject options) {
56
+ map = toCHM(context, options);
57
+ return context.getRuntime().getNil();
58
+ }
59
+
60
+ private ConcurrentHashMapV8<IRubyObject, IRubyObject> toCHM(ThreadContext context, IRubyObject options) {
61
+ Ruby runtime = context.getRuntime();
62
+ if (!options.isNil() && options.respondsTo("[]")) {
63
+ IRubyObject rInitialCapacity = options.callMethod(context, "[]", runtime.newSymbol("initial_capacity"));
64
+ IRubyObject rLoadFactor = options.callMethod(context, "[]", runtime.newSymbol("load_factor"));
65
+ int initialCapacity = !rInitialCapacity.isNil() ? RubyNumeric.num2int(rInitialCapacity.convertToInteger()) : DEFAULT_INITIAL_CAPACITY;
66
+ float loadFactor = !rLoadFactor.isNil() ? (float)RubyNumeric.num2dbl(rLoadFactor.convertToFloat()) : DEFAULT_LOAD_FACTOR;
67
+ return new ConcurrentHashMapV8<IRubyObject, IRubyObject>(initialCapacity, loadFactor);
68
+ } else {
69
+ return new ConcurrentHashMapV8<IRubyObject, IRubyObject>();
70
+ }
71
+ }
72
+
73
+ @JRubyMethod(name = "[]", required = 1)
74
+ public IRubyObject op_aref(ThreadContext context, IRubyObject key) {
75
+ IRubyObject value;
76
+ return ((value = map.get(key)) == null) ? context.getRuntime().getNil() : value;
77
+ }
78
+
79
+ @JRubyMethod(name = {"[]="}, required = 2)
80
+ public IRubyObject op_aset(IRubyObject key, IRubyObject value) {
81
+ map.put(key, value);
82
+ return value;
83
+ }
84
+
85
+ @JRubyMethod
86
+ public IRubyObject put_if_absent(IRubyObject key, IRubyObject value) {
87
+ IRubyObject result = map.putIfAbsent(key, value);
88
+ return result == null ? getRuntime().getNil() : result;
89
+ }
90
+
91
+ @JRubyMethod
92
+ public IRubyObject compute_if_absent(final ThreadContext context, final IRubyObject key, final Block block) {
93
+ return map.computeIfAbsent(key, new ConcurrentHashMapV8.Fun<IRubyObject, IRubyObject>() {
94
+ @Override
95
+ public IRubyObject apply(IRubyObject key) {
96
+ return block.yieldSpecific(context);
97
+ }
98
+ });
99
+ }
100
+
101
+ @JRubyMethod
102
+ public IRubyObject compute_if_present(final ThreadContext context, final IRubyObject key, final Block block) {
103
+ IRubyObject result = map.computeIfPresent(key, new ConcurrentHashMapV8.BiFun<IRubyObject, IRubyObject, IRubyObject>() {
104
+ @Override
105
+ public IRubyObject apply(IRubyObject key, IRubyObject oldValue) {
106
+ IRubyObject result = block.yieldSpecific(context, oldValue);
107
+ return result.isNil() ? null : result;
108
+ }
109
+ });
110
+ return result == null ? context.getRuntime().getNil() : result;
111
+ }
112
+
113
+ @JRubyMethod
114
+ public IRubyObject compute(final ThreadContext context, final IRubyObject key, final Block block) {
115
+ IRubyObject result = map.compute(key, new ConcurrentHashMapV8.BiFun<IRubyObject, IRubyObject, IRubyObject>() {
116
+ @Override
117
+ public IRubyObject apply(IRubyObject key, IRubyObject oldValue) {
118
+ IRubyObject result = block.yieldSpecific(context, oldValue);
119
+ return result.isNil() ? null : result;
120
+ }
121
+ });
122
+ return result == null ? context.getRuntime().getNil() : result;
123
+ }
124
+
125
+ @JRubyMethod
126
+ public IRubyObject merge_pair(final ThreadContext context, final IRubyObject key, final IRubyObject value, final Block block) {
127
+ IRubyObject result = map.merge(key, value, new ConcurrentHashMapV8.BiFun<IRubyObject, IRubyObject, IRubyObject>() {
128
+ @Override
129
+ public IRubyObject apply(IRubyObject oldValue, IRubyObject newValue) {
130
+ IRubyObject result = block.yieldSpecific(context, oldValue);
131
+ return result.isNil() ? null : result;
132
+ }
133
+ });
134
+ return result == null ? context.getRuntime().getNil() : result;
135
+ }
136
+
137
+ @JRubyMethod
138
+ public RubyBoolean replace_pair(IRubyObject key, IRubyObject oldValue, IRubyObject newValue) {
139
+ return getRuntime().newBoolean(map.replace(key, oldValue, newValue));
140
+ }
141
+
142
+ @JRubyMethod(name = {"key?"}, required = 1)
143
+ public RubyBoolean has_key_p(IRubyObject key) {
144
+ return map.containsKey(key) ? getRuntime().getTrue() : getRuntime().getFalse();
145
+ }
146
+
147
+ @JRubyMethod
148
+ public IRubyObject replace_if_exists(IRubyObject key, IRubyObject value) {
149
+ IRubyObject result = map.replace(key, value);
150
+ return result == null ? getRuntime().getNil() : result;
151
+ }
152
+
153
+ @JRubyMethod
154
+ public IRubyObject get_and_set(IRubyObject key, IRubyObject value) {
155
+ IRubyObject result = map.put(key, value);
156
+ return result == null ? getRuntime().getNil() : result;
157
+ }
158
+
159
+ @JRubyMethod
160
+ public IRubyObject delete(IRubyObject key) {
161
+ IRubyObject result = map.remove(key);
162
+ return result == null ? getRuntime().getNil() : result;
163
+ }
164
+
165
+ @JRubyMethod
166
+ public RubyBoolean delete_pair(IRubyObject key, IRubyObject value) {
167
+ return getRuntime().newBoolean(map.remove(key, value));
168
+ }
169
+
170
+ @JRubyMethod
171
+ public IRubyObject clear() {
172
+ map.clear();
173
+ return this;
174
+ }
175
+
176
+ @JRubyMethod
177
+ public IRubyObject each_pair(ThreadContext context, Block block) {
178
+ for (Map.Entry<IRubyObject,IRubyObject> entry : map.entrySet()) {
179
+ block.yieldSpecific(context, entry.getKey(), entry.getValue());
180
+ }
181
+ return this;
182
+ }
183
+
184
+ @JRubyMethod
185
+ public RubyFixnum size(ThreadContext context) {
186
+ return context.getRuntime().newFixnum(map.size());
187
+ }
188
+
189
+ @JRubyMethod
190
+ public IRubyObject get_or_default(IRubyObject key, IRubyObject defaultValue) {
191
+ return map.getValueOrDefault(key, defaultValue);
192
+ }
193
+
194
+ @JRubyMethod(visibility = PRIVATE)
195
+ public JRubyCacheBackend initialize_copy(ThreadContext context, IRubyObject other) {
196
+ this.map = new ConcurrentHashMapV8<IRubyObject, IRubyObject>();
197
+ return this;
198
+ }
199
+ }
200
+ }