ref 1.0.5 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +41 -0
- data/lib/ref.rb +28 -29
- data/lib/ref/abstract_reference_key_map.rb +72 -28
- data/lib/ref/abstract_reference_value_map.rb +61 -18
- data/lib/ref/reference_queue.rb +8 -8
- data/lib/ref/soft_reference.rb +7 -7
- data/lib/ref/version.rb +3 -0
- data/lib/ref/weak_reference/pure_ruby.rb +9 -9
- data/lib/ref_ext.jar +0 -0
- metadata +23 -49
- data/README.rdoc +0 -40
- data/VERSION +0 -1
- data/lib/org/jruby/ext/ref/references.jar +0 -0
- data/lib/ref/mock.rb +0 -150
- data/lib/ref/safe_monitor.rb +0 -50
- data/lib/ref/weak_reference/iron_ruby.rb +0 -14
- data/test/mock_test.rb +0 -33
- data/test/mock_test.rbc +0 -856
- data/test/reference_key_map_behavior.rb +0 -155
- data/test/reference_key_map_behavior.rbc +0 -4241
- data/test/reference_queue_test.rb +0 -60
- data/test/reference_queue_test.rbc +0 -1938
- data/test/reference_value_map_behavior.rb +0 -135
- data/test/reference_value_map_behavior.rbc +0 -3560
- data/test/soft_key_map_test.rb +0 -13
- data/test/soft_key_map_test.rbc +0 -331
- data/test/soft_reference_test.rb +0 -49
- data/test/soft_reference_test.rbc +0 -1481
- data/test/soft_value_map_test.rb +0 -13
- data/test/soft_value_map_test.rbc +0 -331
- data/test/strong_reference_test.rb +0 -15
- data/test/strong_reference_test.rbc +0 -546
- data/test/test_helper.rb +0 -4
- data/test/test_helper.rbc +0 -143
- data/test/weak_key_map_test.rb +0 -13
- data/test/weak_key_map_test.rbc +0 -331
- data/test/weak_reference_test.rb +0 -54
- data/test/weak_reference_test.rbc +0 -1510
- data/test/weak_value_map_test.rb +0 -13
- data/test/weak_value_map_test.rbc +0 -331
data/lib/ref/soft_reference.rb
CHANGED
@@ -19,12 +19,12 @@ module Ref
|
|
19
19
|
class SoftReference < Reference
|
20
20
|
@@strong_references = [{}]
|
21
21
|
@@gc_flag_set = false
|
22
|
-
|
22
|
+
|
23
23
|
# Number of garbage collection cycles after an object is used before a reference to it can be reclaimed.
|
24
24
|
MIN_GC_CYCLES = 10
|
25
|
-
|
26
|
-
@@lock =
|
27
|
-
|
25
|
+
|
26
|
+
@@lock = Monitor.new
|
27
|
+
|
28
28
|
@@finalizer = lambda do |object_id|
|
29
29
|
@@lock.synchronize do
|
30
30
|
while @@strong_references.size >= MIN_GC_CYCLES do
|
@@ -34,14 +34,14 @@ module Ref
|
|
34
34
|
@@gc_flag_set = false
|
35
35
|
end
|
36
36
|
end
|
37
|
-
|
37
|
+
|
38
38
|
# Create a new soft reference to an object.
|
39
39
|
def initialize(obj)
|
40
40
|
@referenced_object_id = obj.__id__
|
41
41
|
@weak_reference = WeakReference.new(obj)
|
42
42
|
add_strong_reference(obj)
|
43
43
|
end
|
44
|
-
|
44
|
+
|
45
45
|
# Get the referenced object. If the object has been reclaimed by the
|
46
46
|
# garbage collector, then this will return nil.
|
47
47
|
def object
|
@@ -50,7 +50,7 @@ module Ref
|
|
50
50
|
add_strong_reference(obj) if obj
|
51
51
|
obj
|
52
52
|
end
|
53
|
-
|
53
|
+
|
54
54
|
private
|
55
55
|
# Create a strong reference to the object. This reference will live
|
56
56
|
# for three passes of the garbage collector.
|
data/lib/ref/version.rb
ADDED
@@ -4,25 +4,25 @@ module Ref
|
|
4
4
|
# subclass Delegator which is very heavy to instantiate and utilizes a
|
5
5
|
# because it does not fair amount of memory under Ruby 1.8.
|
6
6
|
class WeakReference < Reference
|
7
|
-
|
7
|
+
|
8
8
|
class ReferencePointer
|
9
9
|
def initialize(object)
|
10
10
|
@referenced_object_id = object.__id__
|
11
11
|
add_backreference(object)
|
12
12
|
end
|
13
|
-
|
13
|
+
|
14
14
|
def cleanup
|
15
15
|
obj = ObjectSpace._id2ref(@referenced_object_id) rescue nil
|
16
16
|
remove_backreference(obj) if obj
|
17
17
|
end
|
18
|
-
|
18
|
+
|
19
19
|
def object
|
20
20
|
obj = ObjectSpace._id2ref(@referenced_object_id)
|
21
21
|
obj if verify_backreferences(obj)
|
22
22
|
rescue RangeError
|
23
23
|
nil
|
24
24
|
end
|
25
|
-
|
25
|
+
|
26
26
|
private
|
27
27
|
# Verify that the object is the same one originally set for the weak reference.
|
28
28
|
def verify_backreferences(obj) #:nodoc:
|
@@ -30,7 +30,7 @@ module Ref
|
|
30
30
|
backreferences = obj.instance_variable_get(:@__weak_backreferences__) if obj.instance_variable_defined?(:@__weak_backreferences__)
|
31
31
|
backreferences && backreferences.include?(object_id)
|
32
32
|
end
|
33
|
-
|
33
|
+
|
34
34
|
# Add a backreference to the object.
|
35
35
|
def add_backreference(obj) #:nodoc:
|
36
36
|
return unless supports_backreference?(obj)
|
@@ -41,7 +41,7 @@ module Ref
|
|
41
41
|
end
|
42
42
|
backreferences << object_id
|
43
43
|
end
|
44
|
-
|
44
|
+
|
45
45
|
# Remove backreferences from the object.
|
46
46
|
def remove_backreference(obj) #:nodoc:
|
47
47
|
return unless supports_backreference?(obj)
|
@@ -51,16 +51,16 @@ module Ref
|
|
51
51
|
obj.send(:remove_instance_variable, :@__weak_backreferences__) if backreferences.empty?
|
52
52
|
end
|
53
53
|
end
|
54
|
-
|
54
|
+
|
55
55
|
def supports_backreference?(obj)
|
56
56
|
obj.respond_to?(:instance_variable_get) && obj.respond_to?(:instance_variable_defined?)
|
57
57
|
rescue NoMethodError
|
58
58
|
false
|
59
59
|
end
|
60
60
|
end
|
61
|
-
|
61
|
+
|
62
62
|
@@weak_references = {}
|
63
|
-
@@lock =
|
63
|
+
@@lock = Monitor.new
|
64
64
|
|
65
65
|
# Finalizer that cleans up weak references when references are destroyed.
|
66
66
|
@@reference_finalizer = lambda do |object_id|
|
data/lib/ref_ext.jar
ADDED
Binary file
|
metadata
CHANGED
@@ -1,98 +1,72 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ref
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 2.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Brian Durand
|
8
|
-
|
8
|
+
- The Ruby Concurrency Team
|
9
|
+
autorequire:
|
9
10
|
bindir: bin
|
10
11
|
cert_chain: []
|
11
|
-
date:
|
12
|
+
date: 2015-07-10 00:00:00.000000000 Z
|
12
13
|
dependencies: []
|
13
|
-
description: Library that implements weak, soft, and strong references in Ruby that
|
14
|
-
work across multiple runtimes (MRI, REE, YARV, Jruby, Rubinius, and IronRuby). Also
|
15
|
-
includes implementation of maps/hashes that use references and a reference queue.
|
14
|
+
description: Library that implements weak, soft, and strong references in Ruby that work across multiple runtimes (MRI,Jruby and Rubinius). Also includes implementation of maps/hashes that use references and a reference queue.
|
16
15
|
email:
|
17
16
|
- bbdurand@gmail.com
|
17
|
+
- concurrent-ruby@googlegroups.com
|
18
18
|
executables: []
|
19
19
|
extensions: []
|
20
20
|
extra_rdoc_files:
|
21
|
-
- README.
|
21
|
+
- README.md
|
22
22
|
files:
|
23
|
-
- README.rdoc
|
24
|
-
- VERSION
|
25
23
|
- MIT_LICENSE
|
26
|
-
-
|
24
|
+
- README.md
|
25
|
+
- ext/java/org/jruby/ext/ref/ReferencesService.java
|
26
|
+
- ext/java/org/jruby/ext/ref/RubySoftReference.java
|
27
|
+
- ext/java/org/jruby/ext/ref/RubyWeakReference.java
|
28
|
+
- lib/ref.rb
|
27
29
|
- lib/ref/abstract_reference_key_map.rb
|
28
30
|
- lib/ref/abstract_reference_value_map.rb
|
29
|
-
- lib/ref/mock.rb
|
30
31
|
- lib/ref/reference.rb
|
31
32
|
- lib/ref/reference_queue.rb
|
32
|
-
- lib/ref/safe_monitor.rb
|
33
33
|
- lib/ref/soft_key_map.rb
|
34
34
|
- lib/ref/soft_reference.rb
|
35
35
|
- lib/ref/soft_value_map.rb
|
36
36
|
- lib/ref/strong_reference.rb
|
37
|
+
- lib/ref/version.rb
|
37
38
|
- lib/ref/weak_key_map.rb
|
38
|
-
- lib/ref/weak_reference
|
39
|
+
- lib/ref/weak_reference.rb
|
39
40
|
- lib/ref/weak_reference/pure_ruby.rb
|
40
41
|
- lib/ref/weak_reference/weak_ref.rb
|
41
|
-
- lib/ref/weak_reference.rb
|
42
42
|
- lib/ref/weak_value_map.rb
|
43
|
-
- lib/
|
44
|
-
|
45
|
-
- test/mock_test.rbc
|
46
|
-
- test/reference_key_map_behavior.rb
|
47
|
-
- test/reference_key_map_behavior.rbc
|
48
|
-
- test/reference_queue_test.rb
|
49
|
-
- test/reference_queue_test.rbc
|
50
|
-
- test/reference_value_map_behavior.rb
|
51
|
-
- test/reference_value_map_behavior.rbc
|
52
|
-
- test/soft_key_map_test.rb
|
53
|
-
- test/soft_key_map_test.rbc
|
54
|
-
- test/soft_reference_test.rb
|
55
|
-
- test/soft_reference_test.rbc
|
56
|
-
- test/soft_value_map_test.rb
|
57
|
-
- test/soft_value_map_test.rbc
|
58
|
-
- test/strong_reference_test.rb
|
59
|
-
- test/strong_reference_test.rbc
|
60
|
-
- test/test_helper.rb
|
61
|
-
- test/test_helper.rbc
|
62
|
-
- test/weak_key_map_test.rb
|
63
|
-
- test/weak_key_map_test.rbc
|
64
|
-
- test/weak_reference_test.rb
|
65
|
-
- test/weak_reference_test.rbc
|
66
|
-
- test/weak_value_map_test.rb
|
67
|
-
- test/weak_value_map_test.rbc
|
68
|
-
- ext/java/org/jruby/ext/ref/ReferencesService.java
|
69
|
-
- ext/java/org/jruby/ext/ref/RubySoftReference.java
|
70
|
-
- ext/java/org/jruby/ext/ref/RubyWeakReference.java
|
71
|
-
homepage: http://github.com/bdurand/ref
|
43
|
+
- lib/ref_ext.jar
|
44
|
+
homepage: http://github.com/ruby-concurrency/ref
|
72
45
|
licenses:
|
73
46
|
- MIT
|
74
47
|
metadata: {}
|
75
|
-
post_install_message:
|
48
|
+
post_install_message:
|
76
49
|
rdoc_options:
|
77
50
|
- --charset=UTF-8
|
78
51
|
- --main
|
79
|
-
- README.
|
52
|
+
- README.md
|
80
53
|
require_paths:
|
81
54
|
- lib
|
82
55
|
required_ruby_version: !ruby/object:Gem::Requirement
|
83
56
|
requirements:
|
84
57
|
- - '>='
|
85
58
|
- !ruby/object:Gem::Version
|
86
|
-
version:
|
59
|
+
version: 1.9.3
|
87
60
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
88
61
|
requirements:
|
89
62
|
- - '>='
|
90
63
|
- !ruby/object:Gem::Version
|
91
64
|
version: '0'
|
92
65
|
requirements: []
|
93
|
-
rubyforge_project:
|
94
|
-
rubygems_version: 2.
|
95
|
-
signing_key:
|
66
|
+
rubyforge_project:
|
67
|
+
rubygems_version: 2.4.5
|
68
|
+
signing_key:
|
96
69
|
specification_version: 4
|
97
70
|
summary: Library that implements weak, soft, and strong references in Ruby.
|
98
71
|
test_files: []
|
72
|
+
has_rdoc: true
|
data/README.rdoc
DELETED
@@ -1,40 +0,0 @@
|
|
1
|
-
This library provides object references for Ruby as well as some common utilities for working with references. Object references are used to point to other objects and come in three distinct flavors that interact differently with the garbage collector.
|
2
|
-
|
3
|
-
* Ref::StrongReference - This is a plain old pointer to another object.
|
4
|
-
* Ref::WeakReference - This is a pointer to another object, but it is not seen by the garbage collector and the memory used by the object can be reclaimed at any time.
|
5
|
-
* Ref::SoftReference - This is similar to a weak reference, but the garbage collector is not as eager to reclaim the referenced object.
|
6
|
-
|
7
|
-
All of these classes extend from a common Ref::Reference class and have a common interface.
|
8
|
-
|
9
|
-
Weak and soft references are useful when you have instantiated objects that you may want to use again but can recreate if necessary. Since the garbage collector determines when to reclaim the memory used by the objects, you don't need to worry about bloating the Ruby heap.
|
10
|
-
|
11
|
-
= Example Usage
|
12
|
-
|
13
|
-
ref = Ref::WeakReference.new("hello")
|
14
|
-
ref.object # should be "hello"
|
15
|
-
ObjectSpace.garbage_collect
|
16
|
-
ref.object # should be nil (assuming the garbage collector reclaimed the reference)
|
17
|
-
|
18
|
-
= Goodies
|
19
|
-
|
20
|
-
This library also includes tools for some common uses of weak and soft references.
|
21
|
-
|
22
|
-
* Ref::WeakKeyMap - A map of keys to values where the keys are weak references
|
23
|
-
* Ref::WeakValueMap - A map of keys to values where the values are weak references
|
24
|
-
* Ref::SoftKeyMap - A map of keys to values where the keys are soft references
|
25
|
-
* Ref::SoftValueMap - A map of keys to values where the values are soft references
|
26
|
-
* Ref::ReferenceQueue - A thread safe implementation of a queue that will add references to itself as their objects are garbage collected.
|
27
|
-
|
28
|
-
= Problems with WeakRef
|
29
|
-
|
30
|
-
Ruby does come with the WeakRef class in the standard library. However, there are issues with this class across several different Ruby runtimes. This gem provides a common interface to weak references that works across MRI, Ruby Enterprise Edition, YARV, Jruby, Rubinius, and IronRuby.
|
31
|
-
|
32
|
-
1. MRI and REE 1.8 - WeakRef extends from Delegator which is a very heavy weight class under Ruby 1.8. Creating a WeakRef object will allocate thousands of other objects and use up hundreds of kilobytes of memory. This makes WeakRef all but unusable even if you only need several hundred of them.
|
33
|
-
2. YARV 1.9 - WeakRef is unsafe to use because the garbage collector can run in a different system thread than a thread allocating memory. This exposes a bug where a WeakRef may end up pointing to a completely different object than it originally referenced.
|
34
|
-
3. Jruby and IronRuby - Jruby and IronRuby using the Ruby 1.8 libraries suffers from the same performance issue with the Delegator class. Furthermore, these VM's don't implement the method used to load an object from the heap using an object id and so cannot use a pure Ruby method to implement weak references.
|
35
|
-
4. Rubinius - Rubinius implements WeakRef with a lighter weight version of delegation and works very well.
|
36
|
-
5. MRI Ruby 2.0 has a good implementation of WeakRef.
|
37
|
-
|
38
|
-
= BasicObject
|
39
|
-
|
40
|
-
Not that weak references will not work with MRI/REE 1.8 or YARV 1.9. References will be created, but the objects will never be stored so the reference object will always treat the object as if it is always garbage collected. BasicObject does not implement the necessary methods to maintain the reference.
|
data/VERSION
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
1.0.5
|
Binary file
|
data/lib/ref/mock.rb
DELETED
@@ -1,150 +0,0 @@
|
|
1
|
-
module Ref
|
2
|
-
# This module provides mock weak and strong references that are designed to be
|
3
|
-
# used in tests. You can define a block where all weak and soft references created
|
4
|
-
# will be mock references. You can then mimic running the garbage collector on
|
5
|
-
# the objects pointed to by the references.
|
6
|
-
#
|
7
|
-
# Example usage:
|
8
|
-
#
|
9
|
-
# Ref::Mock.use do
|
10
|
-
# obj = Object.new
|
11
|
-
# ref = Ref::WeakReference.new(obj)
|
12
|
-
# ref.object # obj
|
13
|
-
# Ref::Mock.gc(obj) # mimics the garbage collector reclaiming the referenced object
|
14
|
-
# ref.object # nil
|
15
|
-
# end
|
16
|
-
module Mock
|
17
|
-
class << self
|
18
|
-
# Use the mock implementation inside a block and then restore the original implementation.
|
19
|
-
def use
|
20
|
-
if object_space
|
21
|
-
yield
|
22
|
-
else
|
23
|
-
setup
|
24
|
-
begin
|
25
|
-
yield
|
26
|
-
ensure
|
27
|
-
cleanup
|
28
|
-
end
|
29
|
-
end
|
30
|
-
end
|
31
|
-
|
32
|
-
# Start using mock references.
|
33
|
-
def setup
|
34
|
-
raise "Ref::Mock already setup" if object_space
|
35
|
-
|
36
|
-
@object_space = {}
|
37
|
-
|
38
|
-
class << ObjectSpace
|
39
|
-
unless method_defined?(:define_finalizer_with_mock_reference)
|
40
|
-
def define_finalizer_with_mock_reference(obj, finalizer)
|
41
|
-
if ::Ref::Mock.object_space.include?(obj.__id__)
|
42
|
-
::Ref::Mock.object_space[obj.__id__] << finalizer
|
43
|
-
else
|
44
|
-
define_finalizer_without_mock_reference(obj, finalizer)
|
45
|
-
end
|
46
|
-
end
|
47
|
-
end
|
48
|
-
|
49
|
-
alias_method :define_finalizer_without_mock_reference, :define_finalizer
|
50
|
-
alias_method :define_finalizer, :define_finalizer_with_mock_reference
|
51
|
-
end
|
52
|
-
|
53
|
-
class << WeakReference
|
54
|
-
unless method_defined?(:new_with_mock_reference)
|
55
|
-
def new_with_mock_reference(obj)
|
56
|
-
if self == Mock::MockWeakReference
|
57
|
-
new_without_mock_reference(obj)
|
58
|
-
else
|
59
|
-
Mock::MockWeakReference.new(obj)
|
60
|
-
end
|
61
|
-
end
|
62
|
-
end
|
63
|
-
|
64
|
-
alias_method :new_without_mock_reference, :new
|
65
|
-
alias_method :new, :new_with_mock_reference
|
66
|
-
end
|
67
|
-
|
68
|
-
class << SoftReference
|
69
|
-
unless method_defined?(:new_with_mock_reference)
|
70
|
-
def new_with_mock_reference(obj)
|
71
|
-
if self == Mock::MockSoftReference
|
72
|
-
new_without_mock_reference(obj)
|
73
|
-
else
|
74
|
-
Mock::MockSoftReference.new(obj)
|
75
|
-
end
|
76
|
-
end
|
77
|
-
end
|
78
|
-
|
79
|
-
alias_method :new_without_mock_reference, :new
|
80
|
-
alias_method :new, :new_with_mock_reference
|
81
|
-
end
|
82
|
-
end
|
83
|
-
|
84
|
-
# Stop using mock references.
|
85
|
-
def cleanup
|
86
|
-
@object_space = nil
|
87
|
-
class << ObjectSpace
|
88
|
-
alias_method :define_finalizer_with_mock_reference, :define_finalizer
|
89
|
-
alias_method :define_finalizer, :define_finalizer_without_mock_reference
|
90
|
-
end
|
91
|
-
|
92
|
-
class << WeakReference
|
93
|
-
alias_method :new_with_mock_reference, :new
|
94
|
-
alias_method :new, :new_without_mock_reference
|
95
|
-
end
|
96
|
-
|
97
|
-
class << SoftReference
|
98
|
-
alias_method :new_with_mock_reference, :new
|
99
|
-
alias_method :new, :new_without_mock_reference
|
100
|
-
end
|
101
|
-
end
|
102
|
-
|
103
|
-
def object_space # :nodoc:
|
104
|
-
@object_space if instance_variable_defined?(:@object_space)
|
105
|
-
end
|
106
|
-
|
107
|
-
# Simulate garbage collection of the objects passed in as arguments. If no objects
|
108
|
-
# are specified, all objects will be reclaimed.
|
109
|
-
def gc(*objects)
|
110
|
-
objects = if objects.empty?
|
111
|
-
object_space.keys
|
112
|
-
else
|
113
|
-
objects.map { |obj| obj.__id__ }
|
114
|
-
end
|
115
|
-
|
116
|
-
objects.each do |id|
|
117
|
-
finalizers = object_space.delete(id)
|
118
|
-
if finalizers
|
119
|
-
finalizers.each{|finalizer| finalizer.call(id)}
|
120
|
-
end
|
121
|
-
end
|
122
|
-
end
|
123
|
-
end
|
124
|
-
|
125
|
-
module MockReference #:nodoc:
|
126
|
-
def initialize(obj)
|
127
|
-
@object = obj
|
128
|
-
@referenced_object_id = obj.__id__
|
129
|
-
raise "Reference::Mock not setup yet" unless Mock.object_space
|
130
|
-
Mock.object_space[obj.__id__] ||= []
|
131
|
-
end
|
132
|
-
|
133
|
-
def object
|
134
|
-
if @object && Mock.object_space.include?(@object.__id__)
|
135
|
-
@object
|
136
|
-
else
|
137
|
-
@object = nil
|
138
|
-
end
|
139
|
-
end
|
140
|
-
end
|
141
|
-
|
142
|
-
class MockWeakReference < WeakReference #:nodoc:
|
143
|
-
include MockReference
|
144
|
-
end
|
145
|
-
|
146
|
-
class MockSoftReference < SoftReference #:nodoc:
|
147
|
-
include MockReference
|
148
|
-
end
|
149
|
-
end
|
150
|
-
end
|
data/lib/ref/safe_monitor.rb
DELETED
@@ -1,50 +0,0 @@
|
|
1
|
-
begin
|
2
|
-
require 'thread'
|
3
|
-
rescue LoadError
|
4
|
-
# Threads not available. Monitor will do nothing.
|
5
|
-
end
|
6
|
-
|
7
|
-
module Ref
|
8
|
-
# The Monitor class in Ruby 1.8 has some bugs and also threads may not be available on all
|
9
|
-
# runtimes. This class provides a simple, safe re-entrant mutex as an alternative.
|
10
|
-
class SafeMonitor
|
11
|
-
def initialize
|
12
|
-
@owner = nil
|
13
|
-
@count = 0
|
14
|
-
@mutex = defined?(Mutex) ? Mutex.new : nil
|
15
|
-
end
|
16
|
-
|
17
|
-
# Acquire an exclusive lock.
|
18
|
-
def lock
|
19
|
-
if @mutex
|
20
|
-
if @owner != Thread.current.object_id
|
21
|
-
@mutex.lock
|
22
|
-
@owner = Thread.current.object_id
|
23
|
-
end
|
24
|
-
@count += 1
|
25
|
-
end
|
26
|
-
true
|
27
|
-
end
|
28
|
-
|
29
|
-
# Release the exclusive lock.
|
30
|
-
def unlock
|
31
|
-
if @mutex
|
32
|
-
if @owner == Thread.current.object_id
|
33
|
-
@count -= 1
|
34
|
-
if @count == 0
|
35
|
-
@owner = nil
|
36
|
-
@mutex.unlock
|
37
|
-
end
|
38
|
-
end
|
39
|
-
end
|
40
|
-
end
|
41
|
-
|
42
|
-
# Run a block of code with an exclusive lock.
|
43
|
-
def synchronize
|
44
|
-
lock
|
45
|
-
yield
|
46
|
-
ensure
|
47
|
-
unlock
|
48
|
-
end
|
49
|
-
end
|
50
|
-
end
|