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