@@ -324,6 +324,64 @@ AWS_TEST_CASE(
324324 test_s3_buffer_pool_reserve_over_limit_instant_release ,
325325 s_test_s3_buffer_pool_reserve_over_limit_instant_release )
326326
327+
328+ static void s_on_pool_buffer_reserved_instant_release (void * user_data ) {
329+ struct s_reserve_state * state = user_data ;
330+
331+ if (aws_future_s3_buffer_ticket_get_error (state -> future ) == AWS_OP_SUCCESS ) {
332+ state -> ticket = aws_future_s3_buffer_ticket_get_result_by_move (state -> future );
333+ }
334+
335+ state -> future = aws_future_s3_buffer_ticket_release (state -> future );
336+ }
337+
338+ /* release future in the callback right away to check for potential race conditions */
339+ static int s_test_s3_buffer_pool_reserve_over_limit_cancel (struct aws_allocator * allocator , void * ctx ) {
340+ (void )allocator ;
341+ (void )ctx ;
342+
343+ struct aws_s3_buffer_pool * buffer_pool = aws_s3_default_buffer_pool_new (
344+ allocator , (struct aws_s3_buffer_pool_config ){.part_size = MB_TO_BYTES (8 ), .memory_limit = GB_TO_BYTES (1 )});
345+
346+ struct aws_s3_buffer_ticket * tickets [112 ];
347+ struct aws_future_s3_buffer_ticket * ticket_futures [112 ];
348+ for (size_t i = 0 ; i < 112 ; ++ i ) {
349+ ticket_futures [i ] = aws_s3_default_buffer_pool_reserve (
350+ buffer_pool , (struct aws_s3_buffer_pool_reserve_meta ){.size = MB_TO_BYTES (8 )});
351+ ASSERT_TRUE (aws_future_s3_buffer_ticket_is_done (ticket_futures [i ]));
352+ ASSERT_INT_EQUALS (aws_future_s3_buffer_ticket_get_error (ticket_futures [i ]), AWS_OP_SUCCESS );
353+ tickets [i ] = aws_future_s3_buffer_ticket_get_result_by_move (ticket_futures [i ]);
354+ struct aws_byte_buf buf = aws_s3_buffer_ticket_claim (tickets [i ]);
355+ ASSERT_NOT_NULL (buf .buffer );
356+ }
357+
358+ struct aws_future_s3_buffer_ticket * over_future = aws_s3_default_buffer_pool_reserve (
359+ buffer_pool , (struct aws_s3_buffer_pool_reserve_meta ){.size = MB_TO_BYTES (8 )});
360+
361+ ASSERT_FALSE (aws_future_s3_buffer_ticket_is_done (over_future ));
362+
363+ struct s_reserve_state state = {.future = over_future };
364+
365+ aws_future_s3_buffer_ticket_register_callback (over_future , s_on_pool_buffer_reserved_instant_release , & state );
366+
367+ for (size_t i = 0 ; i < 112 ; ++ i ) {
368+ aws_future_s3_buffer_ticket_set_error (ticket_futures [i ], AWS_ERROR_S3_CANCELED );
369+ aws_s3_buffer_ticket_release (tickets [i ]);
370+ aws_future_s3_buffer_ticket_release (ticket_futures [i ]);
371+ }
372+
373+ ASSERT_NOT_NULL (state .ticket );
374+
375+ aws_s3_buffer_ticket_release (state .ticket );
376+
377+ aws_s3_default_buffer_pool_destroy (buffer_pool );
378+
379+ return 0 ;
380+ };
381+ AWS_TEST_CASE (
382+ test_s3_buffer_pool_reserve_over_limit_cancel ,
383+ s_test_s3_buffer_pool_reserve_over_limit_cancel )
384+
327385static int s_test_s3_buffer_pool_too_small (struct aws_allocator * allocator , void * ctx ) {
328386 (void )allocator ;
329387 (void )ctx ;
0 commit comments