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
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 65d0ceb85d4d1208144f2ad51c92269c4f0f689f
|
4
|
+
data.tar.gz: 7ee73e669c4d7532ed44743ea17f4acbd2d983fd
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 22589cec63a2275a3a4f71e903e858d5fe33180a866ac3108c8d4768b08b8f1998dc85e32f8f3a81ce5647b7265e9b4a24a1c22d80ed5368e2e1c6d76167a154
|
7
|
+
data.tar.gz: db38d2ca1d6a8fbe96a2fcb8c6d1308226648928d95c6cf62ece3832fccb7bf7e9241d13f1f87d0d55c1b8cac7715fdb361dc1d50fbdf5351aa896244c78d690
|
data/README.md
ADDED
@@ -0,0 +1,41 @@
|
|
1
|
+
# Ref
|
2
|
+
|
3
|
+
[![Gem Version](https://badge.fury.io/rb/ref.svg)](http://badge.fury.io/rb/ref) [![Build Status](https://travis-ci.org/ruby-concurrency/ref.svg?branch=master)](https://travis-ci.org/ruby-concurrency/ref) [![Coverage Status](https://img.shields.io/coveralls/ruby-concurrency/ref/master.svg)](https://coveralls.io/r/ruby-concurrency/ref) [![Code Climate](https://codeclimate.com/github/ruby-concurrency/ref.svg)](https://codeclimate.com/github/ruby-concurrency/ref) [![Dependency Status](https://gemnasium.com/ruby-concurrency/ref.svg)](https://gemnasium.com/ruby-concurrency/ref) [![License](https://img.shields.io/badge/license-MIT-green.svg)](http://opensource.org/licenses/MIT) [![Gitter chat](http://img.shields.io/badge/gitter-join%20chat%20%E2%86%92-brightgreen.svg)](https://gitter.im/ruby-concurrency/concurrent-ruby)
|
4
|
+
|
5
|
+
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.
|
6
|
+
|
7
|
+
* `Ref::StrongReference` - This is a plain old pointer to another object.
|
8
|
+
* `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.
|
9
|
+
* `Ref::SoftReference` - This is similar to a weak reference, but the garbage collector is not as eager to reclaim the referenced object.
|
10
|
+
|
11
|
+
All of these classes extend from a common `Ref::Reference` class and have a common interface.
|
12
|
+
|
13
|
+
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.
|
14
|
+
|
15
|
+
## Example Usage
|
16
|
+
|
17
|
+
```ruby
|
18
|
+
ref = Ref::WeakReference.new("hello")
|
19
|
+
ref.object # should be "hello"
|
20
|
+
ObjectSpace.garbage_collect
|
21
|
+
ref.object # should be nil (assuming the garbage collector reclaimed the reference)
|
22
|
+
```
|
23
|
+
|
24
|
+
## Goodies
|
25
|
+
|
26
|
+
This library also includes tools for some common uses of weak and soft references.
|
27
|
+
|
28
|
+
* `Ref::WeakKeyMap` - A map of keys to values where the keys are weak references
|
29
|
+
* `Ref::WeakValueMap` - A map of keys to values where the values are weak references
|
30
|
+
* `Ref::SoftKeyMap` - A map of keys to values where the keys are soft references
|
31
|
+
* `Ref::SoftValueMap` - A map of keys to values where the values are soft references
|
32
|
+
* `Ref::ReferenceQueue` - A thread safe implementation of a queue that will add references to itself as their objects are garbage collected.
|
33
|
+
|
34
|
+
## Problems with WeakRef
|
35
|
+
|
36
|
+
Ruby does come with the `WeakRef` class in the standard library. However, there are [issues with this class](https://bugs.ruby-lang.org/issues/4168) across several different Ruby runtimes. This gem provides a common interface to weak references that works across MRI, Ruby Enterprise Edition, YARV, JRuby and Rubinius.
|
37
|
+
|
38
|
+
1. Rubinius - Rubinius implements `WeakRef` with a lighter weight version of delegation and works very well.
|
39
|
+
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.
|
40
|
+
3. MRI Ruby 2.0+ has a good implementation of `WeakRef`.
|
41
|
+
|
data/lib/ref.rb
CHANGED
@@ -1,45 +1,44 @@
|
|
1
1
|
module Ref
|
2
|
-
|
3
|
-
require File.join(File.dirname(__FILE__), "ref", "abstract_reference_key_map.rb")
|
4
|
-
require File.join(File.dirname(__FILE__), "ref", "reference.rb")
|
5
|
-
require File.join(File.dirname(__FILE__), "ref", "reference_queue.rb")
|
6
|
-
require File.join(File.dirname(__FILE__), "ref", "safe_monitor.rb")
|
2
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
7
3
|
|
8
|
-
|
9
|
-
|
10
|
-
|
4
|
+
require 'ref/abstract_reference_value_map'
|
5
|
+
require 'ref/abstract_reference_key_map'
|
6
|
+
require 'ref/reference'
|
7
|
+
require 'ref/reference_queue'
|
8
|
+
|
9
|
+
if defined?(Java)
|
11
10
|
begin
|
12
|
-
|
11
|
+
require 'ref_ext'
|
13
12
|
require 'org/jruby/ext/ref/references'
|
14
|
-
|
15
|
-
|
13
|
+
rescue LoadError
|
14
|
+
require 'ref/soft_reference'
|
15
|
+
require 'ref/weak_reference'
|
16
|
+
warn 'Error loading Rspec rake tasks, probably building the gem...'
|
16
17
|
end
|
17
18
|
else
|
18
|
-
require
|
19
|
-
if defined?(RUBY_ENGINE) && RUBY_ENGINE == '
|
20
|
-
# IronRuby has it's own implementation of weak references.
|
21
|
-
require File.join(File.dirname(__FILE__), "ref", "weak_reference", "iron_ruby.rb")
|
22
|
-
elsif defined?(RUBY_ENGINE) && RUBY_ENGINE == 'rbx'
|
19
|
+
require 'ref/soft_reference'
|
20
|
+
if defined?(RUBY_ENGINE) && RUBY_ENGINE == 'rbx'
|
23
21
|
# If using Rubinius set the implementation to use WeakRef since it is very efficient and using finalizers is not.
|
24
|
-
require
|
22
|
+
require 'ref/weak_reference/weak_ref'
|
25
23
|
elsif defined?(::ObjectSpace::WeakMap)
|
26
24
|
# Ruby 2.0 has a working implementation of weakref.rb backed by the new ObjectSpace::WeakMap
|
27
|
-
require
|
25
|
+
require 'ref/weak_reference/weak_ref'
|
28
26
|
elsif defined?(::ObjectSpace._id2ref)
|
29
27
|
# If ObjectSpace can lookup objects from their object_id, then use the pure ruby implementation.
|
30
|
-
require
|
28
|
+
require 'ref/weak_reference/pure_ruby'
|
31
29
|
else
|
32
30
|
# Otherwise, wrap the standard library WeakRef class
|
33
|
-
require
|
31
|
+
require 'ref/weak_reference/weak_ref'
|
34
32
|
end
|
35
33
|
end
|
36
|
-
|
37
|
-
require
|
38
|
-
require
|
39
|
-
require
|
40
|
-
require
|
41
|
-
require
|
42
|
-
|
43
|
-
|
44
|
-
|
34
|
+
|
35
|
+
require 'ref/soft_key_map'
|
36
|
+
require 'ref/soft_value_map'
|
37
|
+
require 'ref/strong_reference'
|
38
|
+
require 'ref/weak_key_map'
|
39
|
+
require 'ref/weak_value_map'
|
40
|
+
|
41
|
+
def self.jruby?
|
42
|
+
defined?(Java)
|
43
|
+
end
|
45
44
|
end
|
@@ -9,29 +9,33 @@ module Ref
|
|
9
9
|
def reference_class=(klass) #:nodoc:
|
10
10
|
@reference_class = klass
|
11
11
|
end
|
12
|
-
|
12
|
+
|
13
13
|
def reference_class #:nodoc:
|
14
14
|
raise NotImplementedError.new("#{name} is an abstract class and cannot be instantiated") unless @reference_class
|
15
15
|
@reference_class
|
16
16
|
end
|
17
17
|
end
|
18
|
-
|
18
|
+
|
19
19
|
# Create a new map. Values added to the hash will be cleaned up by the garbage
|
20
20
|
# collector if there are no other reference except in the map.
|
21
21
|
def initialize
|
22
22
|
@values = {}
|
23
23
|
@references_to_keys_map = {}
|
24
|
-
@lock =
|
24
|
+
@lock = Monitor.new
|
25
25
|
@reference_cleanup = lambda{|object_id| remove_reference_to(object_id)}
|
26
26
|
end
|
27
27
|
|
28
28
|
# Get a value from the map by key. If the value has been reclaimed by the garbage
|
29
29
|
# collector, this will return nil.
|
30
30
|
def [](key)
|
31
|
-
|
32
|
-
|
31
|
+
@lock.synchronize do
|
32
|
+
rkey = ref_key(key)
|
33
|
+
@values[rkey] if rkey
|
34
|
+
end
|
33
35
|
end
|
34
36
|
|
37
|
+
alias_method :get, :[]
|
38
|
+
|
35
39
|
# Add a key/value to the map.
|
36
40
|
def []=(key, value)
|
37
41
|
ObjectSpace.define_finalizer(key, @reference_cleanup)
|
@@ -41,14 +45,18 @@ module Ref
|
|
41
45
|
end
|
42
46
|
end
|
43
47
|
|
48
|
+
alias_method :put, :[]=
|
49
|
+
|
44
50
|
# Remove the value associated with the key from the map.
|
45
51
|
def delete(key)
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
+
@lock.synchronize do
|
53
|
+
rkey = ref_key(key)
|
54
|
+
if rkey
|
55
|
+
@references_to_keys_map.delete(rkey)
|
56
|
+
@values.delete(rkey)
|
57
|
+
else
|
58
|
+
nil
|
59
|
+
end
|
52
60
|
end
|
53
61
|
end
|
54
62
|
|
@@ -56,14 +64,21 @@ module Ref
|
|
56
64
|
def keys
|
57
65
|
@values.keys.collect{|rkey| @references_to_keys_map[rkey].object}.compact
|
58
66
|
end
|
59
|
-
|
67
|
+
|
60
68
|
# Turn the map into an arry of [key, value] entries.
|
61
69
|
def to_a
|
62
70
|
array = []
|
63
71
|
each{|k,v| array << [k, v]}
|
64
72
|
array
|
65
73
|
end
|
66
|
-
|
74
|
+
|
75
|
+
# Returns a hash containing the names and values for the struct’s members.
|
76
|
+
def to_h
|
77
|
+
hash = {}
|
78
|
+
each{|k,v| hash[k] = v}
|
79
|
+
hash
|
80
|
+
end
|
81
|
+
|
67
82
|
# Iterate through all the key/value pairs in the map that have not been reclaimed
|
68
83
|
# by the garbage collector.
|
69
84
|
def each
|
@@ -81,13 +96,42 @@ module Ref
|
|
81
96
|
end
|
82
97
|
end
|
83
98
|
|
99
|
+
# Returns a new struct containing the contents of `other` and the contents
|
100
|
+
# of `self`. If no block is specified, the value for entries with duplicate
|
101
|
+
# keys will be that of `other`. Otherwise the value for each duplicate key
|
102
|
+
# is determined by calling the block with the key, its value in `self` and
|
103
|
+
# its value in `other`.
|
104
|
+
def merge(other_hash, &block)
|
105
|
+
to_h.merge(other_hash, &block).reduce(self.class.new) do |map, pair|
|
106
|
+
map[pair.first] = pair.last
|
107
|
+
map
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
84
111
|
# Merge the values from another hash into this map.
|
85
112
|
def merge!(other_hash)
|
86
|
-
|
87
|
-
self[key] = value
|
113
|
+
@lock.synchronize do
|
114
|
+
other_hash.each { |key, value| self[key] = value }
|
88
115
|
end
|
89
116
|
end
|
90
117
|
|
118
|
+
# The number of entries in the map
|
119
|
+
def size
|
120
|
+
@references_to_keys_map.count do |_, ref|
|
121
|
+
ref.object
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
alias_method :length, :size
|
126
|
+
|
127
|
+
# True if there are entries that exist in the map
|
128
|
+
def empty?
|
129
|
+
@references_to_keys_map.each do |_, ref|
|
130
|
+
return false if ref.object
|
131
|
+
end
|
132
|
+
true
|
133
|
+
end
|
134
|
+
|
91
135
|
def inspect
|
92
136
|
live_entries = {}
|
93
137
|
each do |key, value|
|
@@ -98,20 +142,20 @@ module Ref
|
|
98
142
|
|
99
143
|
private
|
100
144
|
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
end
|
145
|
+
def ref_key (key)
|
146
|
+
ref = @references_to_keys_map[key.__id__]
|
147
|
+
if ref && ref.object
|
148
|
+
ref.referenced_object_id
|
149
|
+
else
|
150
|
+
nil
|
108
151
|
end
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
152
|
+
end
|
153
|
+
|
154
|
+
def remove_reference_to(object_id)
|
155
|
+
@lock.synchronize do
|
156
|
+
@references_to_keys_map.delete(object_id)
|
157
|
+
@values.delete(object_id)
|
115
158
|
end
|
159
|
+
end
|
116
160
|
end
|
117
161
|
end
|
@@ -9,30 +9,34 @@ module Ref
|
|
9
9
|
def reference_class=(klass) #:nodoc:
|
10
10
|
@reference_class = klass
|
11
11
|
end
|
12
|
-
|
12
|
+
|
13
13
|
def reference_class #:nodoc:
|
14
14
|
raise NotImplementedError.new("#{name} is an abstract class and cannot be instantiated") unless @reference_class
|
15
15
|
@reference_class
|
16
16
|
end
|
17
17
|
end
|
18
|
-
|
18
|
+
|
19
19
|
# Create a new map. Values added to the map will be cleaned up by the garbage
|
20
20
|
# collector if there are no other reference except in the map.
|
21
21
|
def initialize
|
22
22
|
@references = {}
|
23
23
|
@references_to_keys_map = {}
|
24
|
-
@lock =
|
24
|
+
@lock = Monitor.new
|
25
25
|
@reference_cleanup = lambda{|object_id| remove_reference_to(object_id)}
|
26
26
|
end
|
27
27
|
|
28
28
|
# Get a value from the map by key. If the value has been reclaimed by the garbage
|
29
29
|
# collector, this will return nil.
|
30
30
|
def [](key)
|
31
|
-
|
32
|
-
|
33
|
-
|
31
|
+
@lock.synchronize do
|
32
|
+
ref = @references[key]
|
33
|
+
value = ref.object if ref
|
34
|
+
value
|
35
|
+
end
|
34
36
|
end
|
35
37
|
|
38
|
+
alias_method :get, :[]
|
39
|
+
|
36
40
|
# Add a key/value to the map.
|
37
41
|
def []=(key, value)
|
38
42
|
ObjectSpace.define_finalizer(value, @reference_cleanup)
|
@@ -49,6 +53,8 @@ module Ref
|
|
49
53
|
value
|
50
54
|
end
|
51
55
|
|
56
|
+
alias_method :put, :[]=
|
57
|
+
|
52
58
|
# Remove the entry associated with the key from the map.
|
53
59
|
def delete(key)
|
54
60
|
ref = @references.delete(key)
|
@@ -70,14 +76,21 @@ module Ref
|
|
70
76
|
each{|k,v| vals << v}
|
71
77
|
vals
|
72
78
|
end
|
73
|
-
|
79
|
+
|
74
80
|
# Turn the map into an arry of [key, value] entries
|
75
81
|
def to_a
|
76
82
|
array = []
|
77
83
|
each{|k,v| array << [k, v]}
|
78
84
|
array
|
79
85
|
end
|
80
|
-
|
86
|
+
|
87
|
+
# Returns a hash containing the names and values for the struct’s members.
|
88
|
+
def to_h
|
89
|
+
hash = {}
|
90
|
+
each{|k,v| hash[k] = v}
|
91
|
+
hash
|
92
|
+
end
|
93
|
+
|
81
94
|
# Iterate through all the key/value pairs in the map that have not been reclaimed
|
82
95
|
# by the garbage collector.
|
83
96
|
def each
|
@@ -95,13 +108,43 @@ module Ref
|
|
95
108
|
end
|
96
109
|
end
|
97
110
|
|
111
|
+
# Returns a new struct containing the contents of `other` and the contents
|
112
|
+
# of `self`. If no block is specified, the value for entries with duplicate
|
113
|
+
# keys will be that of `other`. Otherwise the value for each duplicate key
|
114
|
+
# is determined by calling the block with the key, its value in `self` and
|
115
|
+
# its value in `other`.
|
116
|
+
def merge(other_hash, &block)
|
117
|
+
to_h.merge(other_hash, &block).reduce(self.class.new) do |map, pair|
|
118
|
+
map[pair.first] = pair.last
|
119
|
+
map
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
98
123
|
# Merge the values from another hash into this map.
|
99
124
|
def merge!(other_hash)
|
100
|
-
|
101
|
-
self[key] = value
|
125
|
+
@lock.synchronize do
|
126
|
+
other_hash.each { |key, value| self[key] = value }
|
102
127
|
end
|
103
128
|
end
|
104
129
|
|
130
|
+
# The number of entries in the map
|
131
|
+
def size
|
132
|
+
@references.count do |_, ref|
|
133
|
+
ref.object
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
alias_method :length, :size
|
138
|
+
|
139
|
+
# True if there are entries that exist in the map
|
140
|
+
def empty?
|
141
|
+
@references.each do |_, ref|
|
142
|
+
return false if ref.object
|
143
|
+
end
|
144
|
+
|
145
|
+
true
|
146
|
+
end
|
147
|
+
|
105
148
|
def inspect
|
106
149
|
live_entries = {}
|
107
150
|
each do |key, value|
|
@@ -112,16 +155,16 @@ module Ref
|
|
112
155
|
|
113
156
|
private
|
114
157
|
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
end
|
122
|
-
@references_to_keys_map.delete(object_id)
|
158
|
+
def remove_reference_to(object_id)
|
159
|
+
@lock.synchronize do
|
160
|
+
keys = @references_to_keys_map[object_id]
|
161
|
+
if keys
|
162
|
+
keys.each do |key|
|
163
|
+
@references.delete(key)
|
123
164
|
end
|
165
|
+
@references_to_keys_map.delete(object_id)
|
124
166
|
end
|
125
167
|
end
|
168
|
+
end
|
126
169
|
end
|
127
170
|
end
|
data/lib/ref/reference_queue.rb
CHANGED
@@ -18,7 +18,7 @@ module Ref
|
|
18
18
|
# # Do something...
|
19
19
|
# end
|
20
20
|
# end
|
21
|
-
#
|
21
|
+
#
|
22
22
|
# queue = Ref::ReferenceQueue.new
|
23
23
|
# ref = MyRef.new(Object.new)
|
24
24
|
# queue.monitor(ref)
|
@@ -30,7 +30,7 @@ module Ref
|
|
30
30
|
def initialize
|
31
31
|
@queue = []
|
32
32
|
@references = {}
|
33
|
-
@lock =
|
33
|
+
@lock = Monitor.new
|
34
34
|
@finalizer = lambda do |object_id|
|
35
35
|
@lock.synchronize do
|
36
36
|
ref = @references.delete(object_id)
|
@@ -38,7 +38,7 @@ module Ref
|
|
38
38
|
end
|
39
39
|
end
|
40
40
|
end
|
41
|
-
|
41
|
+
|
42
42
|
# Monitor a reference. When the object the reference points to is garbage collected,
|
43
43
|
# the reference will be added to the queue.
|
44
44
|
def monitor(reference)
|
@@ -52,7 +52,7 @@ module Ref
|
|
52
52
|
push(reference)
|
53
53
|
end
|
54
54
|
end
|
55
|
-
|
55
|
+
|
56
56
|
# Add a reference to the queue.
|
57
57
|
def push(reference)
|
58
58
|
if reference
|
@@ -61,26 +61,26 @@ module Ref
|
|
61
61
|
end
|
62
62
|
end
|
63
63
|
end
|
64
|
-
|
64
|
+
|
65
65
|
# Pull the last reference off the queue. Returns +nil+ if their are no references.
|
66
66
|
def pop
|
67
67
|
@lock.synchronize do
|
68
68
|
@queue.pop
|
69
69
|
end
|
70
70
|
end
|
71
|
-
|
71
|
+
|
72
72
|
# Pull the next reference off the queue. Returns +nil+ if there are no references.
|
73
73
|
def shift
|
74
74
|
@lock.synchronize do
|
75
75
|
@queue.shift
|
76
76
|
end
|
77
77
|
end
|
78
|
-
|
78
|
+
|
79
79
|
# Return +true+ if the queue is empty.
|
80
80
|
def empty?
|
81
81
|
@queue.empty?
|
82
82
|
end
|
83
|
-
|
83
|
+
|
84
84
|
# Get the current size of the queue.
|
85
85
|
def size
|
86
86
|
@queue.size
|