10
10
import org .jruby .RubyObject ;
11
11
import org .jruby .anno .JRubyClass ;
12
12
import org .jruby .anno .JRubyMethod ;
13
+ import org .jruby .runtime .Block ;
13
14
import org .jruby .runtime .ObjectAllocator ;
14
15
import org .jruby .runtime .ThreadContext ;
15
16
import org .jruby .runtime .builtin .IRubyObject ;
@@ -45,13 +46,13 @@ public IRubyObject initialize(ThreadContext context, IRubyObject value) {
45
46
}
46
47
47
48
@ JRubyMethod
48
- public IRubyObject acquire (ThreadContext context ) throws InterruptedException {
49
- return this .acquire (context , 1 );
49
+ public IRubyObject acquire (ThreadContext context , final Block block ) throws InterruptedException {
50
+ return this .acquire (context , 1 , block );
50
51
}
51
52
52
53
@ JRubyMethod
53
- public IRubyObject acquire (ThreadContext context , IRubyObject permits ) throws InterruptedException {
54
- return this .acquire (context , rubyFixnumToPositiveInt (permits , "permits" ));
54
+ public IRubyObject acquire (ThreadContext context , IRubyObject permits , final Block block ) throws InterruptedException {
55
+ return this .acquire (context , rubyFixnumToPositiveInt (permits , "permits" ), block );
55
56
}
56
57
57
58
@ JRubyMethod (name = "available_permits" )
@@ -65,31 +66,31 @@ public IRubyObject drainPermits(ThreadContext context) {
65
66
}
66
67
67
68
@ JRubyMethod (name = "try_acquire" )
68
- public IRubyObject tryAcquire (ThreadContext context ) throws InterruptedException {
69
+ public IRubyObject tryAcquire (ThreadContext context , final Block block ) throws InterruptedException {
69
70
int permitsInt = 1 ;
70
71
boolean acquired = semaphore .tryAcquire (permitsInt );
71
72
72
- return triedAcquire (context , acquired );
73
+ return triedAcquire (context , permitsInt , acquired , block );
73
74
}
74
75
75
76
@ JRubyMethod (name = "try_acquire" )
76
- public IRubyObject tryAcquire (ThreadContext context , IRubyObject permits ) throws InterruptedException {
77
+ public IRubyObject tryAcquire (ThreadContext context , IRubyObject permits , final Block block ) throws InterruptedException {
77
78
int permitsInt = rubyFixnumToPositiveInt (permits , "permits" );
78
79
boolean acquired = semaphore .tryAcquire (permitsInt );
79
80
80
- return triedAcquire (context , acquired );
81
+ return triedAcquire (context , permitsInt , acquired , block );
81
82
}
82
83
83
84
@ JRubyMethod (name = "try_acquire" )
84
- public IRubyObject tryAcquire (ThreadContext context , IRubyObject permits , IRubyObject timeout ) throws InterruptedException {
85
+ public IRubyObject tryAcquire (ThreadContext context , IRubyObject permits , IRubyObject timeout , final Block block ) throws InterruptedException {
85
86
int permitsInt = rubyFixnumToPositiveInt (permits , "permits" );
86
87
boolean acquired = semaphore .tryAcquire (
87
88
permitsInt ,
88
89
rubyNumericToLong (timeout , "timeout" ),
89
- java .util .concurrent .TimeUnit .SECONDS ,
90
+ java .util .concurrent .TimeUnit .SECONDS
90
91
);
91
92
92
- return triedAcquire (context , acquired );
93
+ return triedAcquire (context , permitsInt , acquired , block );
93
94
}
94
95
95
96
@ JRubyMethod
@@ -110,14 +111,27 @@ public IRubyObject reducePermits(ThreadContext context, IRubyObject reduction) t
110
111
return context .nil ;
111
112
}
112
113
113
- private IRubyObject acquire (ThreadContext context , int permits ) throws InterruptedException {
114
+ private IRubyObject acquire (ThreadContext context , int permits , final Block block ) throws InterruptedException {
114
115
this .semaphore .acquire (permits );
115
116
116
- return context .nil ;
117
+ if (!block .isGiven ()) return context .nil ;
118
+
119
+ try {
120
+ return block .yieldSpecific (context );
121
+ } finally {
122
+ this .semaphore .release (permits );
123
+ }
117
124
}
118
125
119
- private IRubyObject triedAcquire (ThreadContext context , int permits , boolean acquired ) {
120
- return getRuntime ().newBoolean (acquired );
126
+ private IRubyObject triedAcquire (ThreadContext context , int permits , boolean acquired , final Block block ) {
127
+ if (!block .isGiven ()) return getRuntime ().newBoolean (acquired );
128
+ if (!acquired ) return context .nil ;
129
+
130
+ try {
131
+ return block .yieldSpecific (context );
132
+ } finally {
133
+ this .semaphore .release (permits );
134
+ }
121
135
}
122
136
123
137
private int rubyFixnumInt (IRubyObject value , String paramName ) {
0 commit comments