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,9 +46,13 @@ public IRubyObject initialize(ThreadContext context, IRubyObject value) {
45
46
}
46
47
47
48
@ JRubyMethod
48
- public IRubyObject acquire (ThreadContext context , IRubyObject value ) throws InterruptedException {
49
- this .semaphore .acquire (rubyFixnumToPositiveInt (value , "permits" ));
50
- return context .nil ;
49
+ public IRubyObject acquire (ThreadContext context , final Block block ) throws InterruptedException {
50
+ return this .acquire (context , 1 , block );
51
+ }
52
+
53
+ @ JRubyMethod
54
+ public IRubyObject acquire (ThreadContext context , IRubyObject permits , final Block block ) throws InterruptedException {
55
+ return this .acquire (context , rubyFixnumToPositiveInt (permits , "permits" ), block );
51
56
}
52
57
53
58
@ JRubyMethod (name = "available_permits" )
@@ -60,30 +65,32 @@ public IRubyObject drainPermits(ThreadContext context) {
60
65
return getRuntime ().newFixnum (this .semaphore .drainPermits ());
61
66
}
62
67
63
- @ JRubyMethod
64
- public IRubyObject acquire (ThreadContext context ) throws InterruptedException {
65
- this .semaphore .acquire (1 );
66
- return context .nil ;
67
- }
68
-
69
68
@ JRubyMethod (name = "try_acquire" )
70
- public IRubyObject tryAcquire (ThreadContext context ) throws InterruptedException {
71
- return getRuntime ().newBoolean (semaphore .tryAcquire (1 ));
69
+ public IRubyObject tryAcquire (ThreadContext context , final Block block ) throws InterruptedException {
70
+ int permitsInt = 1 ;
71
+ boolean acquired = semaphore .tryAcquire (permitsInt );
72
+
73
+ return triedAcquire (context , permitsInt , acquired , block );
72
74
}
73
75
74
76
@ JRubyMethod (name = "try_acquire" )
75
- public IRubyObject tryAcquire (ThreadContext context , IRubyObject permits ) throws InterruptedException {
76
- return getRuntime ().newBoolean (semaphore .tryAcquire (rubyFixnumToPositiveInt (permits , "permits" )));
77
+ public IRubyObject tryAcquire (ThreadContext context , IRubyObject permits , final Block block ) throws InterruptedException {
78
+ int permitsInt = rubyFixnumToPositiveInt (permits , "permits" );
79
+ boolean acquired = semaphore .tryAcquire (permitsInt );
80
+
81
+ return triedAcquire (context , permitsInt , acquired , block );
77
82
}
78
83
79
84
@ JRubyMethod (name = "try_acquire" )
80
- public IRubyObject tryAcquire (ThreadContext context , IRubyObject permits , IRubyObject timeout ) throws InterruptedException {
81
- return getRuntime ().newBoolean (
82
- semaphore .tryAcquire (
83
- rubyFixnumToPositiveInt (permits , "permits" ),
84
- rubyNumericToLong (timeout , "timeout" ),
85
- java .util .concurrent .TimeUnit .SECONDS )
86
- );
85
+ public IRubyObject tryAcquire (ThreadContext context , IRubyObject permits , IRubyObject timeout , final Block block ) throws InterruptedException {
86
+ int permitsInt = rubyFixnumToPositiveInt (permits , "permits" );
87
+ boolean acquired = semaphore .tryAcquire (
88
+ permitsInt ,
89
+ rubyNumericToLong (timeout , "timeout" ),
90
+ java .util .concurrent .TimeUnit .SECONDS
91
+ );
92
+
93
+ return triedAcquire (context , permitsInt , acquired , block );
87
94
}
88
95
89
96
@ JRubyMethod
@@ -93,8 +100,8 @@ public IRubyObject release(ThreadContext context) {
93
100
}
94
101
95
102
@ JRubyMethod
96
- public IRubyObject release (ThreadContext context , IRubyObject value ) {
97
- this .semaphore .release (rubyFixnumToPositiveInt (value , "permits" ));
103
+ public IRubyObject release (ThreadContext context , IRubyObject permits ) {
104
+ this .semaphore .release (rubyFixnumToPositiveInt (permits , "permits" ));
98
105
return getRuntime ().newBoolean (true );
99
106
}
100
107
@@ -104,6 +111,29 @@ public IRubyObject reducePermits(ThreadContext context, IRubyObject reduction) t
104
111
return context .nil ;
105
112
}
106
113
114
+ private IRubyObject acquire (ThreadContext context , int permits , final Block block ) throws InterruptedException {
115
+ this .semaphore .acquire (permits );
116
+
117
+ if (!block .isGiven ()) return context .nil ;
118
+
119
+ try {
120
+ return block .yieldSpecific (context );
121
+ } finally {
122
+ this .semaphore .release (permits );
123
+ }
124
+ }
125
+
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
+ }
135
+ }
136
+
107
137
private int rubyFixnumInt (IRubyObject value , String paramName ) {
108
138
if (value instanceof RubyFixnum ) {
109
139
RubyFixnum fixNum = (RubyFixnum ) value ;
0 commit comments