Skip to content

Commit 6e26410

Browse files
authored
Round minimum queue capacity up to a power of two (#56)
1 parent 8c67a5d commit 6e26410

File tree

3 files changed

+36
-4
lines changed

3 files changed

+36
-4
lines changed

src/lib.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,14 @@ pub(crate) const VERSION_MAJOR: u16 = 2;
1212
pub(crate) const VERSION_PATCH: u16 = 0;
1313
pub(crate) const VERSION: u32 = (VERSION_MAJOR as u32) << 16 | VERSION_PATCH as u32;
1414

15+
pub(crate) const fn normalized_capacity(capacity: usize) -> usize {
16+
if capacity == 0 {
17+
0
18+
} else {
19+
capacity.next_power_of_two()
20+
}
21+
}
22+
1523
/// `AtomicUsize` with 64-byte alignment for better performance.
1624
#[derive(Default)]
1725
#[repr(C, align(64))]

src/mpmc.rs

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
//! DPDK-style bounded MPMC ring queue
22
3-
use crate::{error::Error, shmem::MappedRegion, CacheAlignedAtomicSize, VERSION};
3+
use crate::{
4+
error::Error, normalized_capacity, shmem::MappedRegion, CacheAlignedAtomicSize, VERSION,
5+
};
46
use core::{marker::PhantomData, ptr::NonNull, sync::atomic::Ordering};
57
use std::{
68
fs::File,
@@ -313,7 +315,7 @@ unsafe impl<T> Sync for Consumer<T> {}
313315
/// page-size requirements.
314316
pub const fn minimum_file_size<T: Sized>(capacity: usize) -> usize {
315317
let buffer_offset = SharedQueueHeader::buffer_offset::<T>();
316-
buffer_offset + capacity * core::mem::size_of::<T>()
318+
buffer_offset + normalized_capacity(capacity) * core::mem::size_of::<T>()
317319
}
318320

319321
struct SharedQueue<T> {
@@ -965,6 +967,17 @@ mod tests {
965967
assert_eq!(values, vec![100, 101]);
966968
}
967969

970+
#[test]
971+
fn test_minimum_file_size_rounds_up_capacity() {
972+
let file = create_temp_shmem_file().unwrap();
973+
let producer = unsafe { Producer::<u64>::create(&file, minimum_file_size::<u64>(3)) }
974+
.expect("create failed");
975+
let consumer = unsafe { Consumer::<u64>::join(&file) }.expect("join failed");
976+
977+
assert_eq!(producer.queue.capacity(), 4);
978+
assert_eq!(consumer.queue.capacity(), 4);
979+
}
980+
968981
#[test]
969982
fn test_multiple_producers_consumers() {
970983
let (file, producer, consumer) = create_test_queue::<Item>(BUFFER_SIZE);

src/spsc.rs

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
use crate::{error::Error, shmem::MappedRegion, CacheAlignedAtomicSize, VERSION};
1+
use crate::{
2+
error::Error, normalized_capacity, shmem::MappedRegion, CacheAlignedAtomicSize, VERSION,
3+
};
24
use core::ptr::NonNull;
35
use std::{
46
fs::File,
@@ -15,7 +17,7 @@ const MAGIC: u64 = 0x7368_6171_7370_7363; // b"shaqspsc"
1517
/// page-size requirements.
1618
pub const fn minimum_file_size<T: Sized>(capacity: usize) -> usize {
1719
let buffer_offset = SharedQueueHeader::buffer_offset::<T>();
18-
buffer_offset + capacity * core::mem::size_of::<T>()
20+
buffer_offset + normalized_capacity(capacity) * core::mem::size_of::<T>()
1921
}
2022

2123
/// Producer side of the SPSC shared queue.
@@ -612,4 +614,13 @@ mod tests {
612614
assert_eq!(*val, 7);
613615
consumer.finalize();
614616
}
617+
618+
#[test]
619+
fn test_minimum_file_size_rounds_up_capacity() {
620+
let file = create_temp_shmem_file().unwrap();
621+
let producer = unsafe { Producer::<u64>::create(&file, minimum_file_size::<u64>(3)) }
622+
.expect("create failed");
623+
624+
assert_eq!(producer.capacity(), 4);
625+
}
615626
}

0 commit comments

Comments
 (0)