hash_queue 0.1.0 → 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.md +6 -1
- data/README.md +15 -3
- data/lib/hash_queue/hash.rb +3 -2
- data/lib/hash_queue/queue.rb +41 -31
- data/lib/hash_queue/version.rb +1 -1
- data/spec/hash_queue/hash_queue_spec.rb +9 -1
- data/spec/hash_queue/queue_spec.rb +30 -0
- data/spec/spec_helper.rb +1 -0
- metadata +2 -2
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,10 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
|
-
## 0.1
|
3
|
+
## 0.1.1
|
4
|
+
|
5
|
+
+ [FEATURE] Added queueing in batches (queueing more items in a single method call)
|
6
|
+
+ [BUGFIX] Fixed bug when popping from HashQueue::Queue with blocking option didn't take nil or an empty array as a valid value [ISSUE#1]
|
7
|
+
|
8
|
+
## 0.1.0
|
4
9
|
|
5
10
|
+ Initial release
|
data/README.md
CHANGED
@@ -46,9 +46,19 @@ hash_queue[:my_queue].queue Stuff.new
|
|
46
46
|
hash_queue.queue :my_queue, Stuff.new
|
47
47
|
```
|
48
48
|
|
49
|
-
|
49
|
+
You can also queue multiple items in a single method call:
|
50
50
|
|
51
|
-
|
51
|
+
```ruby
|
52
|
+
hash_queue[:my_queue].queue_many :foo, :bar, :xyz
|
53
|
+
|
54
|
+
# Ruby itself provides some handy magic syntax for expanding arrays into arguments. The result is identical.
|
55
|
+
stuff = [:foo, :bar, :xyz]
|
56
|
+
hash_queue[:my_queue].queue_many *stuff
|
57
|
+
```
|
58
|
+
|
59
|
+
Keys (or namespaces if you prefer) can be anything you want. Usually those will be symbols or strings but don't need to be. Objects, classes, numbers or even `true` or `nil` will work. Same applies for queued items (but beware if you don't pop with `:size` option, you logically won't be able to distinguish if `nil` you get back is `nil` you queued there or just null return value of popping from an empty queue)
|
60
|
+
|
61
|
+
`#queue` is aliased as `#enqueue`, `#push` and `#<<` for convenience. `#queue_many` is aliased as `#enqueue_many` and `#push_many` accordingly.
|
52
62
|
|
53
63
|
### Working with hash_queue as a whole
|
54
64
|
|
@@ -65,9 +75,11 @@ hash_queue.queue :favourite_rubies, 'rubinius'
|
|
65
75
|
hash_queue.size # => 2
|
66
76
|
```
|
67
77
|
|
78
|
+
Also aliased as `#count` and `#length`.
|
79
|
+
|
68
80
|
##### empty?
|
69
81
|
|
70
|
-
Returns `true` or `false` whether
|
82
|
+
Returns `true` or `false` whether HashQueue instance is empty or not.
|
71
83
|
|
72
84
|
```ruby
|
73
85
|
hash_queue = HashQueue.new
|
data/lib/hash_queue/hash.rb
CHANGED
@@ -89,8 +89,9 @@ module HashQueue
|
|
89
89
|
|
90
90
|
class QueueProxy
|
91
91
|
|
92
|
-
[ :queue, :enqueue, :push, :<<, :
|
93
|
-
|
92
|
+
[ :queue, :enqueue, :push, :<<, :queue_many, :enqueue_many, :push_many,
|
93
|
+
:pop, :shift, :size, :count, :length, :empty?, :clear, :lock, :unlock,
|
94
|
+
:locked?, :unlock_all, :count_locks, :locks_count].each do |m|
|
94
95
|
define_method m do |*args|
|
95
96
|
subject.send m, *args
|
96
97
|
end
|
data/lib/hash_queue/queue.rb
CHANGED
@@ -8,27 +8,33 @@ module HashQueue
|
|
8
8
|
@mutex = Mutex.new
|
9
9
|
@queue = []
|
10
10
|
@locks = []
|
11
|
+
@waiting = []
|
11
12
|
end
|
12
13
|
|
13
|
-
def queue(
|
14
|
+
def queue(*objs)
|
14
15
|
@mutex.synchronize do
|
15
|
-
@queue.
|
16
|
+
@queue.concat objs
|
17
|
+
|
18
|
+
wake_waiting unless @waiting.empty?
|
16
19
|
end
|
17
20
|
end
|
18
21
|
alias_method :enqueue, :queue
|
19
22
|
alias_method :push, :queue
|
20
23
|
alias_method :<<, :queue
|
24
|
+
alias_method :queue_many, :queue
|
25
|
+
alias_method :enqueue_many, :queue
|
26
|
+
alias_method :push_many, :queue
|
21
27
|
|
22
28
|
def pop(options = {}, results = [])
|
23
|
-
|
24
|
-
loop do
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
+
@mutex.synchronize do
|
30
|
+
loop do
|
31
|
+
if options[:blocking] and _empty?
|
32
|
+
@waiting.push Thread.current
|
33
|
+
@mutex.sleep
|
34
|
+
else
|
35
|
+
return _pop(options,results)
|
36
|
+
end
|
29
37
|
end
|
30
|
-
else
|
31
|
-
_pop(options,results)
|
32
38
|
end
|
33
39
|
end
|
34
40
|
alias_method :shift, :pop
|
@@ -56,34 +62,38 @@ module HashQueue
|
|
56
62
|
private
|
57
63
|
|
58
64
|
def _pop(options,results)
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
if
|
63
|
-
|
64
|
-
return []
|
65
|
-
else
|
66
|
-
return nil
|
67
|
-
end
|
68
|
-
end
|
69
|
-
|
70
|
-
(size - _count_locks).times do
|
71
|
-
break if _empty?
|
72
|
-
results.push @queue.shift
|
73
|
-
_lock if options[:lock]
|
74
|
-
end
|
75
|
-
|
76
|
-
if options.key? :size
|
77
|
-
results
|
65
|
+
size = options.fetch(:size, 1)
|
66
|
+
|
67
|
+
if _locked? and _count_locks >= size
|
68
|
+
if options.key? :size
|
69
|
+
return []
|
78
70
|
else
|
79
|
-
|
71
|
+
return nil
|
80
72
|
end
|
81
|
-
end
|
73
|
+
end
|
74
|
+
|
75
|
+
(size - _count_locks).times do
|
76
|
+
break if _empty?
|
77
|
+
results.push @queue.shift
|
78
|
+
_lock if options[:lock]
|
79
|
+
end
|
80
|
+
|
81
|
+
if options.key? :size
|
82
|
+
results
|
83
|
+
else
|
84
|
+
results[0]
|
85
|
+
end
|
82
86
|
end
|
83
87
|
|
84
88
|
def _empty?
|
85
89
|
@queue.empty?
|
86
90
|
end
|
91
|
+
|
92
|
+
def wake_waiting
|
93
|
+
@waiting.shift.wakeup
|
94
|
+
rescue ThreadError
|
95
|
+
retry
|
96
|
+
end
|
87
97
|
|
88
98
|
end
|
89
99
|
end
|
data/lib/hash_queue/version.rb
CHANGED
@@ -1,5 +1,4 @@
|
|
1
1
|
require 'spec_helper'
|
2
|
-
#require 'timeout'
|
3
2
|
|
4
3
|
describe HashQueue do
|
5
4
|
it 'should be able to create new HashQueue instance' do
|
@@ -159,6 +158,15 @@ describe HashQueue::Hash do
|
|
159
158
|
@hash_queue.pop(blocking: true).wont_be_empty
|
160
159
|
end
|
161
160
|
|
161
|
+
it 'should work as expected when an empty array is queued' do
|
162
|
+
Thread.new {
|
163
|
+
sleep 0.5
|
164
|
+
@hash_queue[:foo].queue []
|
165
|
+
}
|
166
|
+
|
167
|
+
Timeout::timeout(0.7) { @hash_queue.pop(blocking: true).must_equal [[]] }
|
168
|
+
end
|
169
|
+
|
162
170
|
end
|
163
171
|
|
164
172
|
end
|
@@ -12,6 +12,16 @@ describe HashQueue::Queue do
|
|
12
12
|
@queue.size.must_equal 0
|
13
13
|
end
|
14
14
|
|
15
|
+
it 'should be able to queue stuff' do
|
16
|
+
@queue.queue :foo
|
17
|
+
@queue.size.must_equal 1
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'should be to queue stuff in batches' do
|
21
|
+
@queue.queue_many :foo, :bar, :xyz
|
22
|
+
@queue.size.must_equal 3
|
23
|
+
end
|
24
|
+
|
15
25
|
end
|
16
26
|
|
17
27
|
describe 'when queued stuff' do
|
@@ -89,6 +99,26 @@ describe HashQueue::Queue do
|
|
89
99
|
@queue.pop(blocking: true, size: 1).wont_be_empty
|
90
100
|
end
|
91
101
|
|
102
|
+
it 'should handle nil in queue' do
|
103
|
+
Thread.new {
|
104
|
+
sleep 0.5
|
105
|
+
@queue.queue_many nil, nil
|
106
|
+
}
|
107
|
+
|
108
|
+
Timeout::timeout(0.7) { @queue.pop(blocking: true).must_equal nil }
|
109
|
+
Timeout::timeout(0.7) { @queue.pop(blocking: true, size: 1).must_equal [nil] }
|
110
|
+
end
|
111
|
+
|
112
|
+
it 'should handle empty array in queue' do
|
113
|
+
Thread.new {
|
114
|
+
sleep 0.5
|
115
|
+
@queue.queue_many [], []
|
116
|
+
}
|
117
|
+
|
118
|
+
Timeout::timeout(0.7) { @queue.pop(blocking: true).must_equal [] }
|
119
|
+
Timeout::timeout(0.7) { @queue.pop(blocking: true, size: 1).must_equal [[]] }
|
120
|
+
end
|
121
|
+
|
92
122
|
end
|
93
123
|
|
94
124
|
describe 'locking' do
|
data/spec/spec_helper.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: hash_queue
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.1
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-09-
|
12
|
+
date: 2012-09-10 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: minitest
|