philiprehberger-queue_stack 0.2.0 → 0.3.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: d2a9266feb351be5204a7e04178e22531c6e74d0a905c71f878eefe8cf94b606
4
- data.tar.gz: e52a17282b21d3961e042bd235e9eb0bcb3885fbc9b5998e15224e07a8e8bbd9
3
+ metadata.gz: 61b9b755594ffadcc05a80b942c0424a29043da9e01c81bc41045c5d440156e1
4
+ data.tar.gz: 823d4982ec931ecf197a42e37ceb7439939a4e6e06070d22ceb437eb1985f2e4
5
5
  SHA512:
6
- metadata.gz: 89a316f59b197ba77230f35da990b9c5ef6c27199466c91cfe039e3574f9b92a217469586975e3814e3ed13a0f9c0223321872d595ec6be07185a15467bc2855
7
- data.tar.gz: cf85a470ea4e242be5f99452d0b74f771187f27037b86e7c17960a5968e9ffe83eaef6eb862c38cae65754901e24053235170e93f58b19173b5e1b36cda12104
6
+ metadata.gz: 0c2f235cd8a6f31bafd5d94af63806e3caabc0fff8743b82815ff90df255f74dbf6d924edccb57e5d73f0fef65958b1c7231e60e96bc9dde9aee3e94718ce0fd
7
+ data.tar.gz: 35d25847836f39bbd80fd7aa8ff07005c126cec030be1d1e9908a4d428d8f96cf2b662167cce8428314aefd7a1ce2384179dd8489e132f1635333e2ffd1dec48
data/CHANGELOG.md CHANGED
@@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [0.3.0] - 2026-04-09
11
+
12
+ ### Added
13
+ - `Queue#try_enqueue(item, timeout: nil)` and `Stack#try_push(item, timeout: nil)` non-blocking insertion variants
14
+ - `Queue#clear` and `Stack#clear` to discard all items and wake blocked producers
15
+
10
16
  ## [0.2.0] - 2026-04-03
11
17
 
12
18
  ### Added
data/README.md CHANGED
@@ -92,6 +92,28 @@ q.each { |item| puts item } # prints 'a', 'b'
92
92
  q.to_a # => ['a', 'b'] (queue unchanged)
93
93
  ```
94
94
 
95
+ ### Non-Blocking Insertion
96
+
97
+ ```ruby
98
+ q = Philiprehberger::QueueStack::Queue.new(capacity: 1)
99
+ q.enqueue('a')
100
+ q.try_enqueue('b') # => false (full, no wait)
101
+ q.try_enqueue('b', timeout: 0.5) # => false after waiting up to 0.5s
102
+
103
+ s = Philiprehberger::QueueStack::Stack.new(capacity: 1)
104
+ s.push('a')
105
+ s.try_push('b') # => false (full, no wait)
106
+ ```
107
+
108
+ ### Clear
109
+
110
+ ```ruby
111
+ q = Philiprehberger::QueueStack::Queue.new
112
+ q.enqueue('a'); q.enqueue('b')
113
+ q.clear
114
+ q.empty? # => true
115
+ ```
116
+
95
117
  ### Close / Shutdown
96
118
 
97
119
  ```ruby
@@ -122,8 +144,10 @@ q.full? # => true
122
144
  |--------|-------------|
123
145
  | `.new(capacity:)` | Create a queue with optional capacity limit |
124
146
  | `#enqueue(item)` | Add item to back (blocks if full) |
147
+ | `#try_enqueue(item, timeout: nil)` | Non-blocking enqueue, returns true/false (waits up to timeout if given) |
125
148
  | `#dequeue` | Remove and return front item (blocks if empty) |
126
149
  | `#try_dequeue(timeout:)` | Dequeue with timeout, returns nil on timeout |
150
+ | `#clear` | Remove all items without returning them |
127
151
  | `#peek` | View front item without removing |
128
152
  | `#drain` | Remove and return all items as array (FIFO order) |
129
153
  | `#each` | Iterate items without removing (returns Enumerator if no block) |
@@ -140,8 +164,10 @@ q.full? # => true
140
164
  |--------|-------------|
141
165
  | `.new(capacity:)` | Create a stack with optional capacity limit |
142
166
  | `#push(item)` | Push item on top (blocks if full) |
167
+ | `#try_push(item, timeout: nil)` | Non-blocking push, returns true/false (waits up to timeout if given) |
143
168
  | `#pop` | Remove and return top item (blocks if empty) |
144
169
  | `#try_pop(timeout:)` | Pop with timeout, returns nil on timeout |
170
+ | `#clear` | Remove all items without returning them |
145
171
  | `#peek` | View top item without removing |
146
172
  | `#drain` | Remove and return all items as array (LIFO order) |
147
173
  | `#each` | Iterate items without removing (returns Enumerator if no block) |
@@ -54,6 +54,48 @@ module Philiprehberger
54
54
  end
55
55
  end
56
56
 
57
+ # Try to enqueue an item without blocking indefinitely.
58
+ #
59
+ # With timeout: nil, returns immediately. With a numeric timeout, waits up to
60
+ # that many seconds for space to become available.
61
+ #
62
+ # @param item [Object] the item to enqueue
63
+ # @param timeout [Numeric, nil] seconds to wait, or nil for non-blocking
64
+ # @return [Boolean] true if enqueued, false if full (or timed out)
65
+ # @raise [ClosedError] if the queue has been closed
66
+ def try_enqueue(item, timeout: nil)
67
+ @mutex.synchronize do
68
+ raise ClosedError, 'cannot enqueue on a closed queue' if @closed
69
+
70
+ if @capacity && @items.length >= @capacity
71
+ return false if timeout.nil? || timeout <= 0
72
+
73
+ deadline = Time.now + timeout
74
+ while @items.length >= @capacity
75
+ remaining = deadline - Time.now
76
+ return false if remaining <= 0
77
+
78
+ @not_full.wait(@mutex, remaining)
79
+ raise ClosedError, 'cannot enqueue on a closed queue' if @closed
80
+ end
81
+ end
82
+
83
+ @items.push(item)
84
+ @not_empty.signal
85
+ true
86
+ end
87
+ end
88
+
89
+ # Remove all items without returning them. Signals any blocked producers.
90
+ #
91
+ # @return [void]
92
+ def clear
93
+ @mutex.synchronize do
94
+ @items.clear
95
+ @not_full.broadcast
96
+ end
97
+ end
98
+
57
99
  # Try to dequeue an item with a timeout.
58
100
  #
59
101
  # @param timeout [Numeric] seconds to wait
@@ -54,6 +54,48 @@ module Philiprehberger
54
54
  end
55
55
  end
56
56
 
57
+ # Try to push an item without blocking indefinitely.
58
+ #
59
+ # With timeout: nil, returns immediately. With a numeric timeout, waits up to
60
+ # that many seconds for space to become available.
61
+ #
62
+ # @param item [Object] the item to push
63
+ # @param timeout [Numeric, nil] seconds to wait, or nil for non-blocking
64
+ # @return [Boolean] true if pushed, false if full (or timed out)
65
+ # @raise [ClosedError] if the stack has been closed
66
+ def try_push(item, timeout: nil)
67
+ @mutex.synchronize do
68
+ raise ClosedError, 'cannot push on a closed stack' if @closed
69
+
70
+ if @capacity && @items.length >= @capacity
71
+ return false if timeout.nil? || timeout <= 0
72
+
73
+ deadline = Time.now + timeout
74
+ while @items.length >= @capacity
75
+ remaining = deadline - Time.now
76
+ return false if remaining <= 0
77
+
78
+ @not_full.wait(@mutex, remaining)
79
+ raise ClosedError, 'cannot push on a closed stack' if @closed
80
+ end
81
+ end
82
+
83
+ @items.push(item)
84
+ @not_empty.signal
85
+ true
86
+ end
87
+ end
88
+
89
+ # Remove all items without returning them. Signals any blocked producers.
90
+ #
91
+ # @return [void]
92
+ def clear
93
+ @mutex.synchronize do
94
+ @items.clear
95
+ @not_full.broadcast
96
+ end
97
+ end
98
+
57
99
  # Try to pop an item with a timeout.
58
100
  #
59
101
  # @param timeout [Numeric] seconds to wait
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Philiprehberger
4
4
  module QueueStack
5
- VERSION = '0.2.0'
5
+ VERSION = '0.3.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.2.0
4
+ version: 0.3.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-03 00:00:00.000000000 Z
11
+ date: 2026-04-09 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