Skip to content

Commit a3bca67

Browse files
committed
Make Thread::Queue and Thread::SizedQueue generic
1 parent 0a8efa1 commit a3bca67

File tree

2 files changed

+173
-61
lines changed

2 files changed

+173
-61
lines changed

core/thread.rbs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1545,7 +1545,7 @@ end
15451545
#
15461546
# consumer.join
15471547
#
1548-
class Thread::Queue < Object
1548+
class Thread::Queue[Elem = untyped] < Object
15491549
# <!-- rdoc-file=thread_sync.c -->
15501550
# Pushes the given `object` to the queue.
15511551
#
@@ -1661,7 +1661,7 @@ class Thread::Queue < Object
16611661
# If `timeout` seconds have passed and no data is available `nil` is returned.
16621662
# If `timeout` is `0` it returns immediately.
16631663
#
1664-
def pop: (?boolish non_block, ?timeout: _ToF?) -> untyped
1664+
def pop: (?boolish non_block, ?timeout: _ToF?) -> Elem?
16651665

16661666
# <!--
16671667
# rdoc-file=thread_sync.c
@@ -1671,7 +1671,7 @@ class Thread::Queue < Object
16711671
# -->
16721672
# Pushes the given `object` to the queue.
16731673
#
1674-
def push: (untyped obj) -> void
1674+
def push: (Elem obj) -> void
16751675

16761676
# <!--
16771677
# rdoc-file=thread_sync.rb
@@ -1692,7 +1692,7 @@ end
16921692
#
16931693
# See Thread::Queue for an example of how a Thread::SizedQueue works.
16941694
#
1695-
class Thread::SizedQueue < Thread::Queue
1695+
class Thread::SizedQueue[Elem = untyped] < Thread::Queue[Elem]
16961696
# <!--
16971697
# rdoc-file=thread_sync.rb
16981698
# - <<(object, non_block = false, timeout: nil)
@@ -1755,7 +1755,8 @@ class Thread::SizedQueue < Thread::Queue
17551755
# If `timeout` seconds have passed and no space is available `nil` is returned.
17561756
# If `timeout` is `0` it returns immediately. Otherwise it returns `self`.
17571757
#
1758-
def push: (untyped obj, ?boolish non_block, timeout: _ToF?) -> void
1758+
def push: (Elem obj, ?boolish non_block) -> void
1759+
| (Elem obj, timeout: _ToF?) -> self?
17591760
end
17601761

17611762
class ConditionVariable = Thread::ConditionVariable

test/stdlib/ThreadQueue_test.rb

Lines changed: 167 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -1,86 +1,197 @@
1+
# frozen_string_literal: true
2+
13
require_relative "test_helper"
4+
require "thread"
25

3-
class ThreadQueueTest < StdlibTest
4-
target Thread::Queue
6+
class Thread__Queue__InstanceTest < Test::Unit::TestCase
7+
include TestHelper
58

6-
def test_lshift
7-
q = Thread::Queue.new
8-
q << :a
9-
end
9+
testing "::Thread::Queue[::Integer]"
1010

11-
def test_clear
12-
q = Thread::Queue.new
13-
q.clear
14-
end
11+
def test_push
12+
queue = Thread::Queue.new
1513

16-
def test_close
17-
q = Thread::Queue.new
18-
q.close
14+
assert_send_type(
15+
"(::Integer) -> void",
16+
queue, :push, 1
17+
)
1918
end
2019

21-
def test_closed?
22-
q = Thread::Queue.new
23-
q.closed?
24-
q.close
25-
q.closed?
20+
def test_length
21+
queue = Thread::Queue.new
22+
23+
assert_send_type(
24+
"() -> ::Integer",
25+
queue, :length
26+
)
2627
end
2728

28-
def test_deq
29-
q = Thread::Queue.new
30-
3.times { q << :a }
29+
def test_num_waiting
30+
queue = Thread::Queue.new
3131

32-
q.deq
33-
q.deq(true)
34-
q.deq(false)
32+
assert_send_type(
33+
"() -> ::Integer",
34+
queue, :num_waiting
35+
)
3536
end
3637

3738
def test_empty?
38-
q = Thread::Queue.new
39-
q.empty?
40-
q << :a
41-
q.empty?
39+
queue = Thread::Queue.new
40+
41+
assert_send_type(
42+
"() -> bool",
43+
queue, :empty?
44+
)
4245
end
4346

44-
def test_enq
45-
q = Thread::Queue.new
46-
q.enq(:a)
47+
def test_closed?
48+
queue = Thread::Queue.new
49+
50+
assert_send_type(
51+
"() -> bool",
52+
queue, :closed?
53+
)
4754
end
4855

49-
def test_length
50-
q = Thread::Queue.new
51-
q.length
56+
def test_close
57+
queue = Thread::Queue.new
58+
59+
assert_send_type(
60+
"() -> void",
61+
queue, :close
62+
)
5263
end
5364

54-
def test_num_waiting
55-
q = Thread::Queue.new
56-
q.num_waiting
65+
def test_clear
66+
queue = Thread::Queue.new
67+
68+
assert_send_type(
69+
"() -> void",
70+
queue, :clear
71+
)
5772
end
5873

5974
def test_pop
60-
q = Thread::Queue.new
61-
3.times { q << :a }
62-
q.pop
63-
q.pop(true)
64-
q.pop(false)
65-
q.pop(timeout: 0.2)
66-
q.pop(timeout: ToF.new(0.1).__with_object_methods(:==))
75+
queue = Thread::Queue.new
76+
77+
queue.push(1)
78+
79+
# Get an Integer from the queue
80+
assert_send_type(
81+
"() -> ::Integer",
82+
queue, :pop
83+
)
84+
85+
queue.push(2)
86+
87+
# Get an Integer from the queue with timeout
88+
assert_send_type(
89+
"(timeout: ::Float) -> ::Integer",
90+
queue, :pop, timeout: 0.1
91+
)
92+
93+
queue.push(3)
94+
95+
# Get an Integer from the queue with `nil` timeout
96+
assert_send_type(
97+
"(timeout: nil) -> ::Integer",
98+
queue, :pop, timeout: nil
99+
)
100+
101+
# Returns `nil` when the queue is empty and with timeout
102+
assert_send_type(
103+
"(timeout: ::Float) -> nil",
104+
queue, :pop, timeout: 0.0
105+
)
106+
107+
queue.push(4)
108+
109+
# With nonblocking is true, but queue is not empty
110+
assert_send_type(
111+
"(bool) -> ::Integer",
112+
queue, :pop, true
113+
)
114+
115+
# Raises an exception with nonblocking but queue is empty
116+
begin
117+
assert_send_type(
118+
"(bool) -> bot",
119+
queue, :pop, true
120+
)
121+
rescue ThreadError
122+
end
123+
124+
queue.close()
125+
126+
# Returns `nil` if the queue is closed
127+
assert_send_type(
128+
"() -> nil",
129+
queue, :pop
130+
)
67131
end
132+
end
68133

69-
def test_push
70-
q = Thread::Queue.new
71-
q.push(:a)
134+
135+
class Thread__SizedQueue__InstanceTest < Test::Unit::TestCase
136+
include TestHelper
137+
138+
testing "::Thread::SizedQueue[::Integer]"
139+
140+
def test_max
141+
queue = Thread::SizedQueue.new(10)
142+
143+
assert_send_type(
144+
"() -> ::Integer",
145+
queue, :max
146+
)
72147
end
73148

74-
def test_shift
75-
q = Thread::Queue.new
76-
3.times { q << :a }
77-
q.shift
78-
q.shift(true)
79-
q.shift(false)
149+
def test_max=
150+
queue = Thread::SizedQueue.new(10)
151+
152+
assert_send_type(
153+
"(::Integer) -> ::Integer",
154+
queue, :max=, 20
155+
)
80156
end
81157

82-
def test_size
83-
q = Thread::Queue.new
84-
q.size
158+
def test_push
159+
queue = Thread::SizedQueue.new(1)
160+
161+
assert_send_type(
162+
"(::Integer) -> void",
163+
queue, :push, 1
164+
)
165+
166+
queue.pop
167+
168+
# Nonblocking mode: queue is not full
169+
assert_send_type(
170+
"(::Integer, bool) -> void",
171+
queue, :push, 2, true
172+
)
173+
174+
# Nonblocking mode: queue is full
175+
begin
176+
assert_send_type(
177+
"(::Integer, bool) -> bot",
178+
queue, :push, 3, true
179+
)
180+
rescue ThreadError
181+
end
182+
183+
queue.pop
184+
185+
# With timeout: queue is not full
186+
assert_send_type(
187+
"(::Integer, timeout: Float) -> ::Thread::SizedQueue[::Integer]",
188+
queue, :push, 3, timeout: 0.3
189+
)
190+
191+
# With timeout: queue is full
192+
assert_send_type(
193+
"(::Integer, timeout: Float) -> nil",
194+
queue, :push, 4, timeout: 0.0
195+
)
85196
end
86197
end

0 commit comments

Comments
 (0)