philiprehberger-queue_stack 0.4.0 → 0.6.0
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 +4 -4
- data/CHANGELOG.md +11 -0
- data/README.md +41 -0
- data/lib/philiprehberger/queue_stack/queue.rb +39 -0
- data/lib/philiprehberger/queue_stack/stack.rb +39 -0
- data/lib/philiprehberger/queue_stack/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: aeb1d7901c33280074ac91777f24b5dcc3704f9d3144dac214a4e8baba9b8bf0
|
|
4
|
+
data.tar.gz: 21a0f6c879d8d1f95270b4d34497e5905064ee96738b30ae9a7bb870c6e3d820
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 28ba1990bc0e94d4c79b414d1a62a69d022f4091d76bd3bdc092e6c377cc0fd7fd79d1a265126aed15bf3a705fa34ac05c05d084990ea867022e03220f23ed7d
|
|
7
|
+
data.tar.gz: d6fc9a7f47a18010cf5b1f7e096861cca61bf565f604c5687a10165cc2074196457e918b3564fe8f80a233ca2e9ad4584929af11b465db4481b3e35f40e0a6ca
|
data/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,17 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.6.0] - 2026-04-27
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
- `Queue#capacity`, `Queue#remaining_capacity`, `Stack#capacity`, `Stack#remaining_capacity` — capacity introspection. `capacity` returns the configured limit (or `nil` for unlimited); `remaining_capacity` returns the number of additional items that can still be accepted (or `nil` for unlimited, `0` when full). Mutex-synchronized for consistent reads.
|
|
14
|
+
|
|
15
|
+
## [0.5.0] - 2026-04-16
|
|
16
|
+
|
|
17
|
+
### Added
|
|
18
|
+
- `Queue#dequeue_if { |item| ... }` conditionally removes and returns the front item only when the block returns truthy; returns `nil` when empty or the block returns false (non-blocking)
|
|
19
|
+
- `Stack#pop_if { |item| ... }` conditionally removes and returns the top item only when the block returns truthy; returns `nil` when empty or the block returns false (non-blocking)
|
|
20
|
+
|
|
10
21
|
## [0.4.0] - 2026-04-15
|
|
11
22
|
|
|
12
23
|
### Added
|
data/README.md
CHANGED
|
@@ -70,6 +70,25 @@ s = Philiprehberger::QueueStack::Stack.new
|
|
|
70
70
|
item = s.try_pop(timeout: 5) # waits up to 5 seconds
|
|
71
71
|
```
|
|
72
72
|
|
|
73
|
+
### Conditional Removal
|
|
74
|
+
|
|
75
|
+
Remove the front/top item only when a predicate holds. Non-blocking; returns `nil` if the collection is empty or the block returns false (the item stays put).
|
|
76
|
+
|
|
77
|
+
```ruby
|
|
78
|
+
q = Philiprehberger::QueueStack::Queue.new
|
|
79
|
+
q.enqueue({ priority: 10 })
|
|
80
|
+
q.enqueue({ priority: 2 })
|
|
81
|
+
|
|
82
|
+
# Only take high-priority work
|
|
83
|
+
q.dequeue_if { |job| job[:priority] >= 5 } # => { priority: 10 }
|
|
84
|
+
q.dequeue_if { |job| job[:priority] >= 5 } # => nil (head priority 2 left intact)
|
|
85
|
+
|
|
86
|
+
s = Philiprehberger::QueueStack::Stack.new
|
|
87
|
+
s.push(:ready)
|
|
88
|
+
s.pop_if { |item| item == :ready } # => :ready
|
|
89
|
+
s.pop_if { |item| item == :ready } # => nil (empty)
|
|
90
|
+
```
|
|
91
|
+
|
|
73
92
|
### Drain
|
|
74
93
|
|
|
75
94
|
```ruby
|
|
@@ -140,6 +159,22 @@ q.full? # => true
|
|
|
140
159
|
# enqueue blocks until space is available
|
|
141
160
|
```
|
|
142
161
|
|
|
162
|
+
### Capacity
|
|
163
|
+
|
|
164
|
+
Read the configured capacity and the number of additional items that can be
|
|
165
|
+
accepted. Both return `nil` for unbounded containers; `remaining_capacity`
|
|
166
|
+
returns `0` when full. Useful for sizing batches or backpressure decisions.
|
|
167
|
+
|
|
168
|
+
```ruby
|
|
169
|
+
q = Philiprehberger::QueueStack::Queue.new(capacity: 100)
|
|
170
|
+
q.capacity # => 100
|
|
171
|
+
q.remaining_capacity # => 100
|
|
172
|
+
50.times { |i| q.enqueue(i) }
|
|
173
|
+
q.remaining_capacity # => 50
|
|
174
|
+
|
|
175
|
+
batch_size = [items.length, q.remaining_capacity].min
|
|
176
|
+
```
|
|
177
|
+
|
|
143
178
|
## API
|
|
144
179
|
|
|
145
180
|
### `Queue`
|
|
@@ -150,6 +185,7 @@ q.full? # => true
|
|
|
150
185
|
| `#enqueue(item)` | Add item to back (blocks if full) |
|
|
151
186
|
| `#try_enqueue(item, timeout: nil)` | Non-blocking enqueue, returns true/false (waits up to timeout if given) |
|
|
152
187
|
| `#dequeue` | Remove and return front item (blocks if empty) |
|
|
188
|
+
| `#dequeue_if { \|item\| ... }` | Remove and return the front item only if the block is truthy (non-blocking) |
|
|
153
189
|
| `#try_dequeue(timeout:)` | Dequeue with timeout, returns nil on timeout |
|
|
154
190
|
| `#clear` | Remove all items without returning them |
|
|
155
191
|
| `#peek` | View front item without removing |
|
|
@@ -162,6 +198,8 @@ q.full? # => true
|
|
|
162
198
|
| `#size` | Number of items |
|
|
163
199
|
| `#empty?` | Whether the queue is empty |
|
|
164
200
|
| `#full?` | Whether the queue is at capacity |
|
|
201
|
+
| `#capacity` | Configured capacity, or `nil` for an unlimited queue |
|
|
202
|
+
| `#remaining_capacity` | Items the queue can still accept (`nil` for unlimited, `0` when full) |
|
|
165
203
|
|
|
166
204
|
### `Stack`
|
|
167
205
|
|
|
@@ -171,6 +209,7 @@ q.full? # => true
|
|
|
171
209
|
| `#push(item)` | Push item on top (blocks if full) |
|
|
172
210
|
| `#try_push(item, timeout: nil)` | Non-blocking push, returns true/false (waits up to timeout if given) |
|
|
173
211
|
| `#pop` | Remove and return top item (blocks if empty) |
|
|
212
|
+
| `#pop_if { \|item\| ... }` | Remove and return the top item only if the block is truthy (non-blocking) |
|
|
174
213
|
| `#try_pop(timeout:)` | Pop with timeout, returns nil on timeout |
|
|
175
214
|
| `#clear` | Remove all items without returning them |
|
|
176
215
|
| `#peek` | View top item without removing |
|
|
@@ -182,6 +221,8 @@ q.full? # => true
|
|
|
182
221
|
| `#size` | Number of items |
|
|
183
222
|
| `#empty?` | Whether the stack is empty |
|
|
184
223
|
| `#full?` | Whether the stack is at capacity |
|
|
224
|
+
| `#capacity` | Configured capacity, or `nil` for an unlimited stack |
|
|
225
|
+
| `#remaining_capacity` | Items the stack can still accept (`nil` for unlimited, `0` when full) |
|
|
185
226
|
|
|
186
227
|
## Development
|
|
187
228
|
|
|
@@ -96,6 +96,24 @@ module Philiprehberger
|
|
|
96
96
|
end
|
|
97
97
|
end
|
|
98
98
|
|
|
99
|
+
# Conditionally dequeue the front item. The block is called with the item
|
|
100
|
+
# that would be dequeued next. If the block returns truthy, the item is
|
|
101
|
+
# removed and returned. Otherwise the item is left in place and +nil+ is
|
|
102
|
+
# returned. Returns +nil+ immediately if the queue is empty (non-blocking).
|
|
103
|
+
#
|
|
104
|
+
# @yield [item] the front item
|
|
105
|
+
# @return [Object, nil] the removed item, or nil if empty or block returned false
|
|
106
|
+
def dequeue_if
|
|
107
|
+
@mutex.synchronize do
|
|
108
|
+
return nil if @items.empty?
|
|
109
|
+
return nil unless yield(@items.first)
|
|
110
|
+
|
|
111
|
+
item = @items.shift
|
|
112
|
+
@not_full.signal
|
|
113
|
+
item
|
|
114
|
+
end
|
|
115
|
+
end
|
|
116
|
+
|
|
99
117
|
# Try to dequeue an item with a timeout.
|
|
100
118
|
#
|
|
101
119
|
# @param timeout [Numeric] seconds to wait
|
|
@@ -207,6 +225,27 @@ module Philiprehberger
|
|
|
207
225
|
def full?
|
|
208
226
|
@mutex.synchronize { @capacity ? @items.length >= @capacity : false }
|
|
209
227
|
end
|
|
228
|
+
|
|
229
|
+
# The configured capacity, or +nil+ for an unlimited queue.
|
|
230
|
+
#
|
|
231
|
+
# @return [Integer, nil]
|
|
232
|
+
def capacity
|
|
233
|
+
@mutex.synchronize { @capacity }
|
|
234
|
+
end
|
|
235
|
+
|
|
236
|
+
# Number of additional items the queue can accept before it is full.
|
|
237
|
+
#
|
|
238
|
+
# Returns +nil+ for unlimited queues. For bounded queues returns
|
|
239
|
+
# +capacity - size+, clamped to a minimum of 0.
|
|
240
|
+
#
|
|
241
|
+
# @return [Integer, nil]
|
|
242
|
+
def remaining_capacity
|
|
243
|
+
@mutex.synchronize do
|
|
244
|
+
next nil unless @capacity
|
|
245
|
+
|
|
246
|
+
[@capacity - @items.length, 0].max
|
|
247
|
+
end
|
|
248
|
+
end
|
|
210
249
|
end
|
|
211
250
|
end
|
|
212
251
|
end
|
|
@@ -96,6 +96,24 @@ module Philiprehberger
|
|
|
96
96
|
end
|
|
97
97
|
end
|
|
98
98
|
|
|
99
|
+
# Conditionally pop the top item. The block is called with the item that
|
|
100
|
+
# would be popped next. If the block returns truthy, the item is removed
|
|
101
|
+
# and returned. Otherwise the item is left in place and +nil+ is returned.
|
|
102
|
+
# Returns +nil+ immediately if the stack is empty (non-blocking).
|
|
103
|
+
#
|
|
104
|
+
# @yield [item] the top item
|
|
105
|
+
# @return [Object, nil] the removed item, or nil if empty or block returned false
|
|
106
|
+
def pop_if
|
|
107
|
+
@mutex.synchronize do
|
|
108
|
+
return nil if @items.empty?
|
|
109
|
+
return nil unless yield(@items.last)
|
|
110
|
+
|
|
111
|
+
item = @items.pop
|
|
112
|
+
@not_full.signal
|
|
113
|
+
item
|
|
114
|
+
end
|
|
115
|
+
end
|
|
116
|
+
|
|
99
117
|
# Try to pop an item with a timeout.
|
|
100
118
|
#
|
|
101
119
|
# @param timeout [Numeric] seconds to wait
|
|
@@ -195,6 +213,27 @@ module Philiprehberger
|
|
|
195
213
|
def full?
|
|
196
214
|
@mutex.synchronize { @capacity ? @items.length >= @capacity : false }
|
|
197
215
|
end
|
|
216
|
+
|
|
217
|
+
# The configured capacity, or +nil+ for an unlimited stack.
|
|
218
|
+
#
|
|
219
|
+
# @return [Integer, nil]
|
|
220
|
+
def capacity
|
|
221
|
+
@mutex.synchronize { @capacity }
|
|
222
|
+
end
|
|
223
|
+
|
|
224
|
+
# Number of additional items the stack can accept before it is full.
|
|
225
|
+
#
|
|
226
|
+
# Returns +nil+ for unlimited stacks. For bounded stacks returns
|
|
227
|
+
# +capacity - size+, clamped to a minimum of 0.
|
|
228
|
+
#
|
|
229
|
+
# @return [Integer, nil]
|
|
230
|
+
def remaining_capacity
|
|
231
|
+
@mutex.synchronize do
|
|
232
|
+
next nil unless @capacity
|
|
233
|
+
|
|
234
|
+
[@capacity - @items.length, 0].max
|
|
235
|
+
end
|
|
236
|
+
end
|
|
198
237
|
end
|
|
199
238
|
end
|
|
200
239
|
end
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: philiprehberger-queue_stack
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.6.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Philip Rehberger
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-04-
|
|
11
|
+
date: 2026-04-28 00:00:00.000000000 Z
|
|
12
12
|
dependencies: []
|
|
13
13
|
description: Thread-safe queue and stack data structures with configurable capacity
|
|
14
14
|
limits, blocking enqueue/dequeue with timeouts, and peek operations. Uses Mutex
|