13
13
import com .oracle .truffle .api .library .CachedLibrary ;
14
14
import com .oracle .truffle .api .profiles .InlinedBranchProfile ;
15
15
import org .truffleruby .annotations .CoreMethod ;
16
+ import org .truffleruby .annotations .Primitive ;
16
17
import org .truffleruby .builtins .CoreMethodArrayArgumentsNode ;
17
- import org .truffleruby .builtins .CoreMethodNode ;
18
18
import org .truffleruby .annotations .CoreModule ;
19
- import org .truffleruby .builtins .NonStandard ;
19
+ import org .truffleruby .builtins .PrimitiveArrayArgumentsNode ;
20
20
import org .truffleruby .core .array .ArrayGuards ;
21
21
import org .truffleruby .core .array .RubyArray ;
22
22
import org .truffleruby .core .array .library .ArrayStoreLibrary ;
23
- import org .truffleruby .core .cast .BooleanCastWithDefaultNode ;
24
23
import org .truffleruby .core .cast .ToANode ;
25
24
import org .truffleruby .core .klass .RubyClass ;
25
+ import org .truffleruby .language .Nil ;
26
26
import org .truffleruby .language .NotProvided ;
27
- import org .truffleruby .language .RubyBaseNodeWithExecute ;
28
- import org .truffleruby .language .RubyNode ;
29
27
import org .truffleruby .annotations .Visibility ;
30
28
import org .truffleruby .language .control .RaiseException ;
31
29
import org .truffleruby .language .objects .AllocationTracing ;
34
32
import com .oracle .truffle .api .CompilerDirectives .TruffleBoundary ;
35
33
import com .oracle .truffle .api .dsl .Cached ;
36
34
import com .oracle .truffle .api .dsl .Cached .Exclusive ;
37
- import com .oracle .truffle .api .dsl .CreateCast ;
38
- import com .oracle .truffle .api .dsl .NodeChild ;
39
35
import com .oracle .truffle .api .dsl .Specialization ;
40
36
41
37
@ CoreModule (value = "Queue" , isClass = true )
@@ -73,18 +69,11 @@ protected RubyQueue push(RubyQueue self, final Object value) {
73
69
74
70
}
75
71
76
- @ CoreMethod (names = { "pop" , "shift" , "deq" }, optional = 1 )
77
- @ NodeChild (value = "queue" , type = RubyNode .class )
78
- @ NodeChild (value = "nonBlocking" , type = RubyBaseNodeWithExecute .class )
79
- public abstract static class PopNode extends CoreMethodNode {
80
-
81
- @ CreateCast ("nonBlocking" )
82
- protected RubyBaseNodeWithExecute coerceToBoolean (RubyBaseNodeWithExecute nonBlocking ) {
83
- return BooleanCastWithDefaultNode .create (false , nonBlocking );
84
- }
72
+ @ Primitive (name = "queue_pop" )
73
+ public abstract static class PopNode extends PrimitiveArrayArgumentsNode {
85
74
86
75
@ Specialization (guards = "!nonBlocking" )
87
- protected Object popBlocking (RubyQueue self , boolean nonBlocking ,
76
+ protected Object popBlocking (RubyQueue self , boolean nonBlocking , Nil timeoutMilliseconds ,
88
77
@ Exclusive @ Cached InlinedBranchProfile closedProfile ) {
89
78
final UnsizedQueue queue = self .queue ;
90
79
@@ -103,61 +92,48 @@ private Object doPop(UnsizedQueue queue) {
103
92
return getContext ().getThreadManager ().runUntilResult (this , queue ::take );
104
93
}
105
94
106
- @ Specialization (guards = "nonBlocking" )
107
- protected Object popNonBlock (RubyQueue self , boolean nonBlocking ,
108
- @ Exclusive @ Cached InlinedBranchProfile errorProfile ) {
95
+ @ Specialization (guards = "! nonBlocking" )
96
+ protected Object popBlocking (RubyQueue self , boolean nonBlocking , long timeoutMilliseconds ,
97
+ @ Exclusive @ Cached InlinedBranchProfile closedProfile ) {
109
98
final UnsizedQueue queue = self .queue ;
99
+ final long deadline = System .currentTimeMillis () + timeoutMilliseconds ;
110
100
111
- final Object value = queue .poll ();
112
-
113
- if (value == null ) {
114
- errorProfile .enter (this );
115
- throw new RaiseException (getContext (), coreExceptions ().threadError ("queue empty" , this ));
116
- } else {
117
- return value ;
118
- }
119
- }
101
+ var result = getContext ().getThreadManager ().runUntilResult (this , () -> {
102
+ final long currentTimeout = deadline - System .currentTimeMillis ();
103
+ final Object value ;
120
104
121
- }
105
+ if (currentTimeout > 0 ) {
106
+ value = queue .poll (currentTimeout );
107
+ } else {
108
+ value = queue .poll ();
109
+ }
122
110
123
- @ NonStandard
124
- @ CoreMethod (names = "receive_timeout" , required = 1 , visibility = Visibility .PRIVATE , lowerFixnum = 1 )
125
- public abstract static class ReceiveTimeoutNode extends CoreMethodArrayArgumentsNode {
111
+ if (value == UnsizedQueue .CLOSED ) {
112
+ closedProfile .enter (this );
113
+ return nil ;
114
+ } else {
115
+ return value ;
116
+ }
117
+ });
126
118
127
- @ Specialization
128
- protected Object receiveTimeout (RubyQueue self , int duration ) {
129
- return receiveTimeout (self , (double ) duration );
119
+ if (result == null ) {
120
+ return nil ;
121
+ }
122
+ return result ;
130
123
}
131
124
132
- @ TruffleBoundary
133
- @ Specialization
134
- protected Object receiveTimeout ( RubyQueue self , double duration ) {
125
+ @ Specialization ( guards = "nonBlocking" )
126
+ protected Object popNonBlock ( RubyQueue self , boolean nonBlocking , Nil timeoutMilliseconds ,
127
+ @ Exclusive @ Cached InlinedBranchProfile errorProfile ) {
135
128
final UnsizedQueue queue = self .queue ;
136
129
137
- final long durationInMillis = (long ) (duration * 1000.0 );
138
- final long start = System .currentTimeMillis ();
139
-
140
- return getContext ().getThreadManager ().runUntilResult (this , () -> {
141
- long now = System .currentTimeMillis ();
142
- long waited = now - start ;
143
- if (waited >= durationInMillis ) {
144
- // Try again to make sure we at least tried once
145
- final Object result = queue .poll ();
146
- return translateResult (result );
147
- }
148
-
149
- final Object result = queue .poll (durationInMillis );
150
- return translateResult (result );
151
- });
152
- }
130
+ final Object value = queue .poll ();
153
131
154
- private Object translateResult (Object result ) {
155
- if (result == null ) {
156
- return false ;
157
- } else if (result == UnsizedQueue .CLOSED ) {
158
- return nil ;
132
+ if (value == null ) {
133
+ errorProfile .enter (this );
134
+ throw new RaiseException (getContext (), coreExceptions ().threadError ("queue empty" , this ));
159
135
} else {
160
- return result ;
136
+ return value ;
161
137
}
162
138
}
163
139
0 commit comments