philiprehberger-queue_stack 0.3.0 → 0.5.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 61b9b755594ffadcc05a80b942c0424a29043da9e01c81bc41045c5d440156e1
4
- data.tar.gz: 823d4982ec931ecf197a42e37ceb7439939a4e6e06070d22ceb437eb1985f2e4
3
+ metadata.gz: dba395bc3ee76baae4cdbbbb100fc91103049635c386e02fe5ac3ae118e9997a
4
+ data.tar.gz: 921a8e4241383d570d951e154b19e7abcce5cdb682d93b42888d36c9804871a2
5
5
  SHA512:
6
- metadata.gz: 0c2f235cd8a6f31bafd5d94af63806e3caabc0fff8743b82815ff90df255f74dbf6d924edccb57e5d73f0fef65958b1c7231e60e96bc9dde9aee3e94718ce0fd
7
- data.tar.gz: 35d25847836f39bbd80fd7aa8ff07005c126cec030be1d1e9908a4d428d8f96cf2b662167cce8428314aefd7a1ce2384179dd8489e132f1635333e2ffd1dec48
6
+ metadata.gz: 30320f35b2ae5d2e01221091e203c31cc799ec5d6a1ff279a0201a04dd9c038f254ad8319d1e4f8cf3a50e1e292e2522a813e8330383f2f49ce99b86d5704b1c
7
+ data.tar.gz: 2ddd79499fa0b97b99fcb45c5c941984c1f8b3ddeee25cc4edeed317b9317509d9ade981940ca685266770db6dc3d472b11e3fdb8610b45731abd44f7f3a284e
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.5.0] - 2026-04-16
11
+
12
+ ### Added
13
+ - `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)
14
+ - `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)
15
+
16
+ ## [0.4.0] - 2026-04-15
17
+
18
+ ### Added
19
+ - `Queue#peek_at(index)` returns the item at the given position without removing it, supporting negative indices like `Array#[]` and returning `nil` when out of range
20
+
10
21
  ## [0.3.0] - 2026-04-09
11
22
 
12
23
  ### Added
data/README.md CHANGED
@@ -40,9 +40,13 @@ item = q.dequeue # => 'task'
40
40
  q = Philiprehberger::QueueStack::Queue.new(capacity: 10)
41
41
  q.enqueue('first')
42
42
  q.enqueue('second')
43
- q.dequeue # => 'first'
44
- q.peek # => 'second'
45
- q.size # => 1
43
+ q.enqueue('third')
44
+ q.peek # => 'first'
45
+ q.peek_at(1) # => 'second'
46
+ q.peek_at(-1) # => 'third'
47
+ q.peek_at(99) # => nil (out of range)
48
+ q.dequeue # => 'first'
49
+ q.size # => 2
46
50
  ```
47
51
 
48
52
  ### Stack (LIFO)
@@ -66,6 +70,25 @@ s = Philiprehberger::QueueStack::Stack.new
66
70
  item = s.try_pop(timeout: 5) # waits up to 5 seconds
67
71
  ```
68
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
+
69
92
  ### Drain
70
93
 
71
94
  ```ruby
@@ -146,9 +169,11 @@ q.full? # => true
146
169
  | `#enqueue(item)` | Add item to back (blocks if full) |
147
170
  | `#try_enqueue(item, timeout: nil)` | Non-blocking enqueue, returns true/false (waits up to timeout if given) |
148
171
  | `#dequeue` | Remove and return front item (blocks if empty) |
172
+ | `#dequeue_if { \|item\| ... }` | Remove and return the front item only if the block is truthy (non-blocking) |
149
173
  | `#try_dequeue(timeout:)` | Dequeue with timeout, returns nil on timeout |
150
174
  | `#clear` | Remove all items without returning them |
151
175
  | `#peek` | View front item without removing |
176
+ | `#peek_at(index)` | View item at the given position (supports negative indices, returns nil if out of range) |
152
177
  | `#drain` | Remove and return all items as array (FIFO order) |
153
178
  | `#each` | Iterate items without removing (returns Enumerator if no block) |
154
179
  | `#to_a` | Snapshot as array (FIFO order) |
@@ -166,6 +191,7 @@ q.full? # => true
166
191
  | `#push(item)` | Push item on top (blocks if full) |
167
192
  | `#try_push(item, timeout: nil)` | Non-blocking push, returns true/false (waits up to timeout if given) |
168
193
  | `#pop` | Remove and return top item (blocks if empty) |
194
+ | `#pop_if { \|item\| ... }` | Remove and return the top item only if the block is truthy (non-blocking) |
169
195
  | `#try_pop(timeout:)` | Pop with timeout, returns nil on timeout |
170
196
  | `#clear` | Remove all items without returning them |
171
197
  | `#peek` | View top item without removing |
@@ -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
@@ -175,6 +193,18 @@ module Philiprehberger
175
193
  @mutex.synchronize { @items.first }
176
194
  end
177
195
 
196
+ # Peek at the item at the given position without removing it.
197
+ #
198
+ # Indexing follows +Array#[]+ semantics: +0+ is the front of the queue,
199
+ # +size - 1+ is the back, and negative indices count from the back
200
+ # (+-1+ is the last item). Returns +nil+ when the index is out of range.
201
+ #
202
+ # @param index [Integer] position in the queue (supports negative indices)
203
+ # @return [Object, nil] the item at the position or nil if out of range
204
+ def peek_at(index)
205
+ @mutex.synchronize { @items[index] }
206
+ end
207
+
178
208
  # Return the number of items in the queue.
179
209
  #
180
210
  # @return [Integer]
@@ -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
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Philiprehberger
4
4
  module QueueStack
5
- VERSION = '0.3.0'
5
+ VERSION = '0.5.0'
6
6
  end
7
7
  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.3.0
4
+ version: 0.5.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-09 00:00:00.000000000 Z
11
+ date: 2026-04-16 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