Skip to content

Commit c7760e6

Browse files
committed
[GR-19220] Add timeout to Queue#pop
PullRequest: truffleruby/3819
2 parents 6f5a242 + d0c8d48 commit c7760e6

File tree

17 files changed

+148
-146
lines changed

17 files changed

+148
-146
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ Compatibility:
2121
* Add `String#bytesplice` (#3039, @itarato).
2222
* Add `String#byteindex` and `String#byterindex` (#3039, @itarato).
2323
* Add implementations of `rb_proc_call_with_block`, `rb_proc_call_kw`, `rb_proc_call_with_block_kw` and `rb_funcall_with_block_kw` (#3068, @andrykonchin).
24+
* Add optional `timeout` argument to `Thread::Queue#pop` (#3039, @itarato).
2425

2526
Performance:
2627

lib/truffle/thread.rb

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,4 +29,15 @@ class ThreadError < StandardError
2929
class Thread
3030
Queue = ::Queue
3131
SizedQueue = ::SizedQueue
32+
33+
class Queue
34+
def pop(non_block = false, timeout: nil)
35+
Primitive.queue_pop(
36+
self,
37+
Primitive.as_boolean(non_block),
38+
Truffle::QueueOperations.validate_and_prepare_timeout(non_block, timeout))
39+
end
40+
alias_method :shift, :pop
41+
alias_method :deq, :pop
42+
end
3243
end

lib/truffle/timeout.rb

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -83,15 +83,15 @@ def abort
8383
end
8484
end
8585

86-
@chan = Truffle::Channel.new
86+
@chan = Queue.new
8787

8888
def self.watch_channel
8989
reqs = []
9090

9191
loop do
9292
begin
9393
while reqs.empty?
94-
req = @chan.receive
94+
req = @chan.pop
9595
reqs << req if req
9696
end
9797

@@ -101,7 +101,7 @@ def self.watch_channel
101101
if min.left > 0
102102
before = Time.now
103103

104-
new_req = @chan.receive_timeout(min.left)
104+
new_req = @chan.pop(timeout: min.left)
105105

106106
slept_for = Time.now - before
107107
else

spec/ruby/core/queue/deq_spec.rb

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,13 @@
11
require_relative '../../spec_helper'
22
require_relative '../../shared/queue/deque'
3+
require_relative '../../shared/types/rb_num2dbl_fails'
34

45
describe "Queue#deq" do
56
it_behaves_like :queue_deq, :deq, -> { Queue.new }
67
end
8+
9+
describe "Queue operations with timeout" do
10+
ruby_version_is "3.2" do
11+
it_behaves_like :rb_num2dbl_fails, nil, -> v { q = Queue.new; q.push(1); q.deq(timeout: v) }
12+
end
13+
end

spec/ruby/core/queue/pop_spec.rb

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,13 @@
11
require_relative '../../spec_helper'
22
require_relative '../../shared/queue/deque'
3+
require_relative '../../shared/types/rb_num2dbl_fails'
34

45
describe "Queue#pop" do
56
it_behaves_like :queue_deq, :pop, -> { Queue.new }
67
end
8+
9+
describe "Queue operations with timeout" do
10+
ruby_version_is "3.2" do
11+
it_behaves_like :rb_num2dbl_fails, nil, -> v { q = Queue.new; q.push(1); q.pop(timeout: v) }
12+
end
13+
end

spec/ruby/core/queue/shift_spec.rb

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,13 @@
11
require_relative '../../spec_helper'
22
require_relative '../../shared/queue/deque'
3+
require_relative '../../shared/types/rb_num2dbl_fails'
34

45
describe "Queue#shift" do
56
it_behaves_like :queue_deq, :shift, -> { Queue.new }
67
end
8+
9+
describe "Queue operations with timeout" do
10+
ruby_version_is "3.2" do
11+
it_behaves_like :rb_num2dbl_fails, nil, -> v { q = Queue.new; q.push(1); q.shift(timeout: v) }
12+
end
13+
end

spec/ruby/shared/queue/deque.rb

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,15 @@
3737
q.send(@method).should == 1
3838
end
3939

40+
it "converts false-ish for non_blocking to boolean" do
41+
q = @object.call
42+
q << 1
43+
q << 2
44+
45+
q.send(@method, false).should == 1
46+
q.send(@method, nil).should == 2
47+
end
48+
4049
it "returns nil for a closed empty queue" do
4150
q = @object.call
4251
q.close
@@ -143,5 +152,13 @@
143152
q.close
144153
-> { q.send(@method, true) }.should raise_error(ThreadError)
145154
end
155+
156+
it "converts true-ish non_blocking argument to true" do
157+
q = @object.call
158+
159+
-> { q.send(@method, true) }.should raise_error(ThreadError)
160+
-> { q.send(@method, 1) }.should raise_error(ThreadError)
161+
-> { q.send(@method, "") }.should raise_error(ThreadError)
162+
end
146163
end
147164
end
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
#
2+
# Shared tests for rb_num2dbl related conversion failures.
3+
#
4+
# Usage example:
5+
# it_behaves_like :rb_num2dbl_fails, nil, -> v { o = A.new; o.foo(v) }
6+
#
7+
8+
describe :rb_num2dbl_fails, shared: true do
9+
it "fails if string is provided" do
10+
-> { @object.call("123") }.should raise_error(TypeError, "no implicit conversion to float from string")
11+
end
12+
13+
it "fails if boolean is provided" do
14+
-> { @object.call(true) }.should raise_error(TypeError, "no implicit conversion to float from true")
15+
-> { @object.call(false) }.should raise_error(TypeError, "no implicit conversion to float from false")
16+
end
17+
end

spec/truffle/objspace/define_finalizer_spec.rb

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,17 +27,17 @@
2727
# The assumption is that this works as expected but is just hard to test.
2828

2929
it "will call the finalizer" do
30-
channel = Truffle::Channel.new
30+
queue = Queue.new
3131
finalizer = proc {
32-
channel.send :finalized
32+
queue << :finalized
3333
}
3434
Object.new.tap do |object|
3535
ObjectSpace.define_finalizer object, finalizer
3636
ObjectSpace.reachable_objects_from(object).should include(finalizer)
3737
end
3838
Primitive.gc_force
3939
Truffle::Debug.drain_finalization_queue # Not needed for correctness
40-
channel.receive_timeout(TIME_TOLERANCE).should == :finalized
40+
queue.pop(timeout: TIME_TOLERANCE).should == :finalized
4141
end
4242

4343
end

spec/truffle/objspace/undefine_finalizer_spec.rb

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,10 @@
1717
# See comment in define_finalizer_spec.rb
1818

1919
it "successfully unregisters a finalizer" do
20-
channel = Truffle::Channel.new
20+
queue = Queue.new
2121
Object.new.tap do |object|
2222
finalizer = proc {
23-
channel.send :finalized
23+
queue << :finalized
2424
}
2525
ObjectSpace.define_finalizer object, finalizer
2626
ObjectSpace.reachable_objects_from(object).should include(finalizer)
@@ -29,7 +29,7 @@
2929
end
3030
Primitive.gc_force
3131
Truffle::Debug.drain_finalization_queue # Not needed for correctness
32-
channel.try_receive.should be_nil
32+
queue.should.empty?
3333
end
3434

3535
end

0 commit comments

Comments
 (0)