12
12
// See the License for the specific language governing permissions and
13
13
// limitations under the License.
14
14
15
+ use std:: future:: Future ;
16
+ use std:: pin:: pin;
15
17
use std:: sync:: Arc ;
18
+ use std:: task:: Context ;
19
+ use std:: task:: RawWaker ;
20
+ use std:: task:: RawWakerVTable ;
21
+ use std:: task:: Waker ;
16
22
use std:: vec:: Vec ;
17
23
18
24
use super :: * ;
@@ -137,6 +143,22 @@ fn try_acquire_concurrently() {
137
143
assert_eq ! ( s. available_permits( ) , 1 ) ;
138
144
}
139
145
146
+ #[ test]
147
+ fn acquire_then_drop ( ) {
148
+ let waker = noop_waker ( ) ;
149
+ let mut context = Context :: from_waker ( & waker) ;
150
+
151
+ let s = Semaphore :: new ( 1 ) ;
152
+ let p1 = s. try_acquire ( 1 ) . unwrap ( ) ;
153
+ {
154
+ let p2 = s. acquire ( 1 ) ;
155
+ let poll = pin ! ( p2) . poll ( & mut context) ;
156
+ assert ! ( poll. is_pending( ) ) ;
157
+ }
158
+ drop ( p1) ;
159
+ assert_eq ! ( s. available_permits( ) , 1 ) ;
160
+ }
161
+
140
162
#[ tokio:: test]
141
163
async fn acquire_then_forget_exact ( ) {
142
164
let s = Arc :: new ( Semaphore :: new ( 5 ) ) ;
@@ -161,3 +183,21 @@ async fn acquire_then_forget_exact() {
161
183
acquired. wait ( ) . await ;
162
184
assert_eq ! ( s. available_permits( ) , 3 ) ;
163
185
}
186
+
187
+ fn noop_waker ( ) -> Waker {
188
+ const NOOP : RawWaker = {
189
+ const VTABLE : RawWakerVTable = RawWakerVTable :: new (
190
+ // Cloning just returns a new no-op raw waker
191
+ |_| NOOP ,
192
+ // `wake` does nothing
193
+ |_| { } ,
194
+ // `wake_by_ref` does nothing
195
+ |_| { } ,
196
+ // Dropping does nothing as we don't allocate anything
197
+ |_| { } ,
198
+ ) ;
199
+ RawWaker :: new ( std:: ptr:: null ( ) , & VTABLE )
200
+ } ;
201
+
202
+ unsafe { Waker :: from_raw ( NOOP ) }
203
+ }
0 commit comments