@@ -268,6 +268,62 @@ static int s_test_s3_buffer_pool_reserve_over_limit(struct aws_allocator *alloca
268268};
269269AWS_TEST_CASE (test_s3_buffer_pool_reserve_over_limit , s_test_s3_buffer_pool_reserve_over_limit )
270270
271+ static void s_on_pool_buffer_reserved_instant_release (void * user_data ) {
272+ struct s_reserve_state * state = user_data ;
273+
274+ if (aws_future_s3_buffer_ticket_get_error (state -> future ) == AWS_OP_SUCCESS ) {
275+ state -> ticket = aws_future_s3_buffer_ticket_get_result_by_move (state -> future );
276+ }
277+
278+ state -> future = aws_future_s3_buffer_ticket_release (state -> future );
279+ }
280+
281+ /* release future in the callback right away to check for potential race conditions */
282+ static int s_test_s3_buffer_pool_reserve_over_limit_instant_release (struct aws_allocator * allocator , void * ctx ) {
283+ (void )allocator ;
284+ (void )ctx ;
285+
286+ struct aws_s3_buffer_pool * buffer_pool = aws_s3_default_buffer_pool_new (
287+ allocator , (struct aws_s3_buffer_pool_config ){.part_size = MB_TO_BYTES (8 ), .memory_limit = GB_TO_BYTES (1 )});
288+
289+ struct aws_s3_buffer_ticket * tickets [112 ];
290+ struct aws_future_s3_buffer_ticket * ticket_futures [112 ];
291+ for (size_t i = 0 ; i < 112 ; ++ i ) {
292+ ticket_futures [i ] = aws_s3_default_buffer_pool_reserve (
293+ buffer_pool , (struct aws_s3_buffer_pool_reserve_meta ){.size = MB_TO_BYTES (8 )});
294+ ASSERT_TRUE (aws_future_s3_buffer_ticket_is_done (ticket_futures [i ]));
295+ ASSERT_INT_EQUALS (aws_future_s3_buffer_ticket_get_error (ticket_futures [i ]), AWS_OP_SUCCESS );
296+ tickets [i ] = aws_future_s3_buffer_ticket_get_result_by_move (ticket_futures [i ]);
297+ struct aws_byte_buf buf = aws_s3_buffer_ticket_claim (tickets [i ]);
298+ ASSERT_NOT_NULL (buf .buffer );
299+ }
300+
301+ struct aws_future_s3_buffer_ticket * over_future = aws_s3_default_buffer_pool_reserve (
302+ buffer_pool , (struct aws_s3_buffer_pool_reserve_meta ){.size = MB_TO_BYTES (8 )});
303+
304+ ASSERT_FALSE (aws_future_s3_buffer_ticket_is_done (over_future ));
305+
306+ struct s_reserve_state state = {.future = over_future };
307+
308+ aws_future_s3_buffer_ticket_register_callback (over_future , s_on_pool_buffer_reserved_instant_release , & state );
309+
310+ for (size_t i = 0 ; i < 112 ; ++ i ) {
311+ aws_s3_buffer_ticket_release (tickets [i ]);
312+ aws_future_s3_buffer_ticket_release (ticket_futures [i ]);
313+ }
314+
315+ ASSERT_NOT_NULL (state .ticket );
316+
317+ aws_s3_buffer_ticket_release (state .ticket );
318+
319+ aws_s3_default_buffer_pool_destroy (buffer_pool );
320+
321+ return 0 ;
322+ };
323+ AWS_TEST_CASE (
324+ test_s3_buffer_pool_reserve_over_limit_instant_release ,
325+ s_test_s3_buffer_pool_reserve_over_limit_instant_release )
326+
271327static int s_test_s3_buffer_pool_too_small (struct aws_allocator * allocator , void * ctx ) {
272328 (void )allocator ;
273329 (void )ctx ;
0 commit comments