From e6c4cb0a755489762b82918bb9955cec7bec0c42 Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Wed, 7 Oct 2026 16:11:45 +0900 Subject: [PATCH] Use rb_len_t for Thread::Queue lengths The ring buffer of Queue and the limit of SizedQueue are element counts that are filled from and compared with Array lengths, so they would truncate on mswin once rb_len_t widens. Co-Authored-By: Claude Opus 5.5 --- thread_sync.c | 24 ++++++++++++------------ thread_sync.rb | 8 ++++---- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/thread_sync.c b/thread_sync.c index 01a49bdaadd..3637d454f95 100644 --- a/thread_sync.c +++ b/thread_sync.c @@ -39,9 +39,9 @@ struct queue_sleep_arg { #define MUTEX_ALLOW_TRAP FL_USER1 static void -sync_wakeup(struct ccan_list_head *head, long max) +sync_wakeup(struct ccan_list_head *head, rb_len_t max) { - RUBY_DEBUG_LOG("max:%ld", max); + RUBY_DEBUG_LOG("max:%"PRIdLEN, max); struct sync_waiter *cur = 0, *next; @@ -663,9 +663,9 @@ rb_mutex_allow_trap(VALUE self, int val) struct rb_queue { struct ccan_list_head waitq; rb_serial_t fork_gen; - long capa; - long len; - long offset; + rb_len_t capa; + rb_len_t len; + rb_len_t offset; VALUE *buffer; int num_waiting; }; @@ -677,7 +677,7 @@ struct rb_szqueue { struct rb_queue q; int num_waiting_push; struct ccan_list_head pushq; - long max; + rb_len_t max; }; static void @@ -685,7 +685,7 @@ queue_mark_and_move(void *ptr) { struct rb_queue *q = ptr; /* no need to mark threads in waitq, they are on stack */ - for (long index = 0; index < q->len; index++) { + for (rb_len_t index = 0; index < q->len; index++) { rb_gc_mark_and_move(&q->buffer[((q->offset + index) % q->capa)]); } } @@ -894,7 +894,7 @@ queue_closed_result(VALUE self, struct rb_queue *q) #define QUEUE_INITIAL_CAPA 8 static inline void -ring_buffer_init(struct rb_queue *q, long initial_capa) +ring_buffer_init(struct rb_queue *q, rb_len_t initial_capa) { q->buffer = ALLOC_N(VALUE, initial_capa); q->capa = initial_capa; @@ -921,7 +921,7 @@ ring_buffer_push(VALUE self, struct rb_queue *q, VALUE obj) ring_buffer_expand(q); } RUBY_ASSERT(q->capa > q->len); - long index = (q->offset + q->len) % q->capa; + rb_len_t index = (q->offset + q->len) % q->capa; q->len++; RB_OBJ_WRITE(self, &q->buffer[index], obj); } @@ -954,8 +954,8 @@ queue_initialize(rb_execution_context_t *ec, VALUE self, VALUE initial) } else { initial = rb_to_array(initial); - long len = RARRAY_LEN(initial); - long initial_capa = QUEUE_INITIAL_CAPA; + rb_len_t len = RARRAY_LEN(initial); + rb_len_t initial_capa = QUEUE_INITIAL_CAPA; while (initial_capa < len) { initial_capa *= 2; } @@ -1079,7 +1079,7 @@ queue_clear(struct rb_queue *q) static VALUE szqueue_initialize(rb_execution_context_t *ec, VALUE self, VALUE vmax) { - long max = NUM2LONG(vmax); + rb_len_t max = NUM2LEN(vmax); struct rb_szqueue *sq = raw_szqueue_ptr(self); if (max <= 0) { diff --git a/thread_sync.rb b/thread_sync.rb index bab21788bc4..70af99ac0f1 100644 --- a/thread_sync.rb +++ b/thread_sync.rb @@ -145,7 +145,7 @@ class Thread # # Returns the length of the queue. def length - Primitive.cexpr!('LONG2NUM(queue_ptr(self)->len)') + Primitive.cexpr!('LEN2NUM(queue_ptr(self)->len)') end alias_method :size, :length @@ -284,7 +284,7 @@ class Thread # Returns the maximum size of the queue. def max - Primitive.cexpr!('LONG2NUM(szqueue_ptr(self)->max)') + Primitive.cexpr!('LEN2NUM(szqueue_ptr(self)->max)') end # call-seq: max=(number) @@ -292,12 +292,12 @@ class Thread # Sets the maximum size of the queue to the given +number+. def max=(vmax) Primitive.cstmt! %{ - long max = NUM2LONG(vmax); + rb_len_t max = NUM2LEN(vmax); if (max <= 0) { rb_raise(rb_eArgError, "queue size must be positive"); } - long diff = 0; + rb_len_t diff = 0; struct rb_szqueue *sq = szqueue_ptr(self); if (max > sq->max) {