@@ -1238,8 +1238,8 @@ pub const TypeErasedQueue = struct {
12381238
12391239 /// Ring buffer. This data is logically *after* queued getters.
12401240 buffer : []u8 ,
1241- put_index : usize ,
1242- get_index : usize ,
1241+ start : usize ,
1242+ len : usize ,
12431243
12441244 putters : std.DoublyLinkedList ,
12451245 getters : std.DoublyLinkedList ,
@@ -1260,8 +1260,8 @@ pub const TypeErasedQueue = struct {
12601260 return .{
12611261 .mutex = .init ,
12621262 .buffer = buffer ,
1263- .put_index = 0 ,
1264- .get_index = 0 ,
1263+ .start = 0 ,
1264+ .len = 0 ,
12651265 .putters = .{},
12661266 .getters = .{},
12671267 };
@@ -1286,6 +1286,16 @@ pub const TypeErasedQueue = struct {
12861286 };
12871287 }
12881288
1289+ fn puttableSlice (q : * const TypeErasedQueue ) ? []u8 {
1290+ const unwrapped_index = q .start + q .len ;
1291+ const wrapped_index , const overflow = @subWithOverflow (unwrapped_index , q .buffer .len );
1292+ const slice = switch (overflow ) {
1293+ 1 = > q .buffer [unwrapped_index .. ],
1294+ 0 = > q .buffer [wrapped_index .. q .start ],
1295+ };
1296+ return if (slice .len > 0 ) slice else null ;
1297+ }
1298+
12891299 fn putLocked (q : * TypeErasedQueue , io : Io , elements : []const u8 , min : usize , uncancelable : bool ) Cancelable ! usize {
12901300 // Getters have first priority on the data, and only when the getters
12911301 // queue is empty do we start populating the buffer.
@@ -1306,20 +1316,12 @@ pub const TypeErasedQueue = struct {
13061316 return elements .len ;
13071317 }
13081318
1309- {
1310- const available = q .buffer [q .put_index .. ];
1311- const copy_len = @min (available .len , remaining .len );
1312- @memcpy (available [0.. copy_len ], remaining [0.. copy_len ]);
1313- remaining = remaining [copy_len .. ];
1314- q .put_index += copy_len ;
1315- if (remaining .len == 0 ) return elements .len ;
1316- }
1317- {
1318- const available = q .buffer [0.. q .get_index ];
1319- const copy_len = @min (available .len , remaining .len );
1320- @memcpy (available [0.. copy_len ], remaining [0.. copy_len ]);
1319+ while (q .puttableSlice ()) | slice | {
1320+ const copy_len = @min (slice .len , remaining .len );
1321+ assert (copy_len > 0 );
1322+ @memcpy (slice [0.. copy_len ], remaining [0.. copy_len ]);
1323+ q .len += copy_len ;
13211324 remaining = remaining [copy_len .. ];
1322- q .put_index = copy_len ;
13231325 if (remaining .len == 0 ) return elements .len ;
13241326 }
13251327
@@ -1354,46 +1356,32 @@ pub const TypeErasedQueue = struct {
13541356 };
13551357 }
13561358
1359+ fn gettableSlice (q : * const TypeErasedQueue ) ? []const u8 {
1360+ const overlong_slice = q .buffer [q .start .. ];
1361+ const slice = overlong_slice [0.. @min (overlong_slice .len , q .len )];
1362+ return if (slice .len > 0 ) slice else null ;
1363+ }
1364+
13571365 fn getLocked (q : * @This (), io : Io , buffer : []u8 , min : usize , uncancelable : bool ) Cancelable ! usize {
13581366 // The ring buffer gets first priority, then data should come from any
13591367 // queued putters, then finally the ring buffer should be filled with
13601368 // data from putters so they can be resumed.
13611369
13621370 var remaining = buffer ;
1363- if (q .get_index <= q .put_index ) {
1364- const available = q .buffer [q .get_index .. q .put_index ];
1365- const copy_len = @min (available .len , remaining .len );
1366- @memcpy (remaining [0.. copy_len ], available [0.. copy_len ]);
1367- q .get_index += copy_len ;
1371+ while (q .gettableSlice ()) | slice | {
1372+ const copy_len = @min (slice .len , remaining .len );
1373+ assert (copy_len > 0 );
1374+ @memcpy (remaining [0.. copy_len ], slice [0.. copy_len ]);
1375+ q .start += copy_len ;
1376+ if (q .buffer .len - q .start == 0 ) q .start = 0 ;
1377+ q .len -= copy_len ;
13681378 remaining = remaining [copy_len .. ];
13691379 if (remaining .len == 0 ) {
13701380 q .fillRingBufferFromPutters (io );
13711381 return buffer .len ;
13721382 }
1373- } else {
1374- {
1375- const available = q .buffer [q .get_index .. ];
1376- const copy_len = @min (available .len , remaining .len );
1377- @memcpy (remaining [0.. copy_len ], available [0.. copy_len ]);
1378- q .get_index += copy_len ;
1379- remaining = remaining [copy_len .. ];
1380- if (remaining .len == 0 ) {
1381- q .fillRingBufferFromPutters (io );
1382- return buffer .len ;
1383- }
1384- }
1385- {
1386- const available = q .buffer [0.. q .put_index ];
1387- const copy_len = @min (available .len , remaining .len );
1388- @memcpy (remaining [0.. copy_len ], available [0.. copy_len ]);
1389- q .get_index = copy_len ;
1390- remaining = remaining [copy_len .. ];
1391- if (remaining .len == 0 ) {
1392- q .fillRingBufferFromPutters (io );
1393- return buffer .len ;
1394- }
1395- }
13961383 }
1384+
13971385 // Copy directly from putters into buffer.
13981386 while (q .putters .popFirst ()) | putter_node | {
13991387 const putter : * Put = @alignCast (@fieldParentPtr ("node" , putter_node ));
@@ -1410,6 +1398,7 @@ pub const TypeErasedQueue = struct {
14101398 q .fillRingBufferFromPutters (io );
14111399 return buffer .len ;
14121400 }
1401+
14131402 // Both ring buffer and putters queue is empty.
14141403 const total_filled = buffer .len - remaining .len ;
14151404 if (total_filled >= min ) return total_filled ;
@@ -1432,30 +1421,20 @@ pub const TypeErasedQueue = struct {
14321421 fn fillRingBufferFromPutters (q : * TypeErasedQueue , io : Io ) void {
14331422 while (q .putters .popFirst ()) | putter_node | {
14341423 const putter : * Put = @alignCast (@fieldParentPtr ("node" , putter_node ));
1435- {
1436- const available = q .buffer [q .put_index .. ];
1437- const copy_len = @min (available .len , putter .remaining .len );
1438- @memcpy (available [0.. copy_len ], putter .remaining [0.. copy_len ]);
1424+ while (q .puttableSlice ()) | slice | {
1425+ const copy_len = @min (slice .len , putter .remaining .len );
1426+ assert (copy_len > 0 );
1427+ @memcpy (slice [0.. copy_len ], putter .remaining [0.. copy_len ]);
1428+ q .len += copy_len ;
14391429 putter .remaining = putter .remaining [copy_len .. ];
1440- q .put_index += copy_len ;
14411430 if (putter .remaining .len == 0 ) {
14421431 putter .condition .signal (io );
1443- continue ;
1444- }
1445- }
1446- {
1447- const available = q .buffer [0.. q .get_index ];
1448- const copy_len = @min (available .len , putter .remaining .len );
1449- @memcpy (available [0.. copy_len ], putter .remaining [0.. copy_len ]);
1450- putter .remaining = putter .remaining [copy_len .. ];
1451- q .put_index = copy_len ;
1452- if (putter .remaining .len == 0 ) {
1453- putter .condition .signal (io );
1454- continue ;
1432+ break ;
14551433 }
1434+ } else {
1435+ q .putters .prepend (putter_node );
1436+ break ;
14561437 }
1457- q .putters .prepend (putter_node );
1458- break ;
14591438 }
14601439 }
14611440};
0 commit comments