@@ -109,6 +109,7 @@ struct aws_s3_default_buffer_pool {
109109struct s3_pending_reserve {
110110 struct aws_linked_list_node node ;
111111 struct aws_future_s3_buffer_ticket * ticket_future ;
112+ struct aws_s3_buffer_ticket * ticket ;
112113 struct aws_s3_buffer_pool_reserve_meta meta ;
113114};
114115
@@ -292,9 +293,6 @@ void aws_s3_default_buffer_pool_destroy(struct aws_s3_buffer_pool *buffer_pool_w
292293
293294 aws_array_list_clean_up (& buffer_pool -> blocks );
294295
295- /* There should be no pending reserves */
296- AWS_FATAL_ASSERT (aws_linked_list_empty (& buffer_pool -> pending_reserves ));
297-
298296 while (!aws_linked_list_empty (& buffer_pool -> pending_reserves )) {
299297 struct aws_linked_list_node * node = aws_linked_list_front (& buffer_pool -> pending_reserves );
300298 struct s3_pending_reserve * pending = AWS_CONTAINER_OF (node , struct s3_pending_reserve , node );
@@ -336,6 +334,11 @@ struct aws_s3_default_buffer_ticket *s_try_reserve(
336334 struct aws_s3_buffer_pool * buffer_pool ,
337335 struct aws_s3_buffer_pool_reserve_meta meta );
338336
337+ struct aws_s3_default_buffer_pool_pending_reservation {
338+ struct aws_future_s3_buffer_ticket * future ;
339+ struct aws_s3_default_buffer_ticket * ticket ;
340+ };
341+
339342static void s_aws_ticket_wrapper_destroy (void * data ) {
340343 struct aws_s3_buffer_ticket * ticket_wrapper = data ;
341344 struct aws_s3_default_buffer_ticket * ticket = ticket_wrapper -> impl ;
@@ -393,58 +396,63 @@ static void s_aws_ticket_wrapper_destroy(void *data) {
393396 aws_mem_release (buffer_pool -> base_allocator , ticket );
394397 aws_mem_release (buffer_pool -> base_allocator , ticket_wrapper );
395398
396- struct aws_future_s3_buffer_ticket * pending_ticket_future_to_fill = NULL ;
397- struct aws_s3_default_buffer_ticket * new_ticket = NULL ;
399+ struct aws_linked_list pending_reserves_to_remove ;
400+ aws_linked_list_init ( & pending_reserves_to_remove ) ;
398401
399- struct aws_linked_list pending_nodes_to_remove ;
400- aws_linked_list_init (& pending_nodes_to_remove );
402+ struct aws_linked_list pending_reserves_to_complete ;
403+ aws_linked_list_init (& pending_reserves_to_complete );
401404
402405 /* Capture all the pending reserves that are done (currently can only happen when request is canceled, which cancels
403406 * pending futures) */
404- for ( struct aws_linked_list_node * node = aws_linked_list_begin (& buffer_pool -> pending_reserves );
405- node != aws_linked_list_end (& buffer_pool -> pending_reserves ); ) {
407+ struct aws_linked_list_node * node = aws_linked_list_begin (& buffer_pool -> pending_reserves );
408+ while ( node != aws_linked_list_end (& buffer_pool -> pending_reserves )) {
406409 struct s3_pending_reserve * pending_reserve = AWS_CONTAINER_OF (node , struct s3_pending_reserve , node );
407410 struct aws_linked_list_node * current_node = node ;
408411 node = aws_linked_list_next (node );
409-
410412 if (aws_future_s3_buffer_ticket_is_done (pending_reserve -> ticket_future )) {
411413 AWS_FATAL_ASSERT (aws_future_s3_buffer_ticket_get_error (pending_reserve -> ticket_future ) != AWS_OP_SUCCESS );
412414 aws_linked_list_remove (current_node );
413-
414- aws_linked_list_push_back (& pending_nodes_to_remove , current_node );
415+ aws_linked_list_push_back (& pending_reserves_to_remove , current_node );
415416 }
416417 }
417418
418- if (!aws_linked_list_empty (& buffer_pool -> pending_reserves )) {
419+ /* Capture all the pending reserves that can be completed. They will actually be completed once outside the mutex.
420+ */
421+ while (!aws_linked_list_empty (& buffer_pool -> pending_reserves )) {
419422 struct aws_linked_list_node * node = aws_linked_list_front (& buffer_pool -> pending_reserves );
420423 struct s3_pending_reserve * pending_reserve = AWS_CONTAINER_OF (node , struct s3_pending_reserve , node );
421424
422- new_ticket = s_try_reserve (pool , pending_reserve -> meta );
425+ pending_reserve -> ticket = s_try_reserve (pool , pending_reserve -> meta );
423426
424- if (new_ticket != NULL ) {
425- pending_ticket_future_to_fill = pending_reserve -> ticket_future ;
427+ if (pending_reserve -> ticket != NULL ) {
426428 aws_linked_list_pop_front (& buffer_pool -> pending_reserves );
427- aws_mem_release (buffer_pool -> base_allocator , pending_reserve );
429+ aws_linked_list_push_back (& pending_reserves_to_complete , node );
430+ } else {
431+ break ;
428432 }
429433 }
430434
431435 aws_mutex_unlock (& buffer_pool -> mutex );
432436
433437 /* release completed pending nodes outside of lock to avoid any deadlocks */
434- while (!aws_linked_list_empty (& pending_nodes_to_remove )) {
435- struct aws_linked_list_node * node = aws_linked_list_front (& pending_nodes_to_remove );
438+ while (!aws_linked_list_empty (& pending_reserves_to_remove )) {
439+ struct aws_linked_list_node * node = aws_linked_list_front (& pending_reserves_to_remove );
436440 struct s3_pending_reserve * pending = AWS_CONTAINER_OF (node , struct s3_pending_reserve , node );
437441 aws_future_s3_buffer_ticket_release (pending -> ticket_future );
438- aws_linked_list_pop_front (& pending_nodes_to_remove );
442+ aws_linked_list_pop_front (& pending_reserves_to_remove );
439443 aws_mem_release (buffer_pool -> base_allocator , pending );
440444 }
441445
442446 /* fill the next pending future */
443- if ( pending_ticket_future_to_fill != NULL ) {
444- struct aws_s3_buffer_ticket * new_ticket_wrapper = s_wrap_default_ticket ( new_ticket );
445- aws_future_s3_buffer_ticket_set_result_by_move ( pending_ticket_future_to_fill , & new_ticket_wrapper );
447+ while (! aws_linked_list_empty ( & pending_reserves_to_complete ) ) {
448+ struct aws_linked_list_node * node = aws_linked_list_front ( & pending_reserves_to_remove );
449+ struct s3_pending_reserve * pending = AWS_CONTAINER_OF ( node , struct s3_pending_reserve , node );
446450
447- aws_future_s3_buffer_ticket_release (pending_ticket_future_to_fill );
451+ struct aws_s3_buffer_ticket * new_ticket_wrapper = s_wrap_default_ticket (pending -> ticket );
452+ aws_future_s3_buffer_ticket_set_result_by_move (pending -> ticket_future , & new_ticket_wrapper );
453+
454+ aws_future_s3_buffer_ticket_release (pending -> ticket_future );
455+ aws_mem_release (buffer_pool -> base_allocator , pending );
448456 }
449457}
450458
0 commit comments