Skip to content

feat: bidirectional pipe#34

Open
yhdengh wants to merge 2 commits into
mainfrom
arca-networking-pr
Open

feat: bidirectional pipe#34
yhdengh wants to merge 2 commits into
mainfrom
arca-networking-pr

Conversation

@yhdengh
Copy link
Copy Markdown
Contributor

@yhdengh yhdengh commented Jun 5, 2026

This PR adds a no_std bidirectional pipe implementation shared by vmm-side and Arca-side

yhdengh and others added 2 commits June 5, 2026 15:56
Co-authored-by: ruiting-chen <ruiting.chen.soc@gmail.com>
Comment thread common/src/pipe/ring.rs
}

impl RingHeader {
/// Bytes available to read. Called by the consumer.
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The current choices of Ordering depend on that read is only ever modified by the consumer and used_space is only ever invoked by the consumer. This info should be somewhere in the comment

Comment thread common/src/pipe/ring.rs
/// Owns `(ptr, size)` together so call sites don't juggle them.
/// Wrap-around is handled inside `write_at` / `read_at`.
pub struct RingData {
ptr: *mut u8,
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not &mut [u8]? Is there a reason for RingData to need a raw pointer?


/// Bytes written by this producer that the consumer has not yet read.
/// Uses Acquire on read_cursor so this can be called cross-thread safely.
pub fn bytes_pending(&self) -> u64 {
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How is this different from Ring::free_space()?

}

/// True when both ends of this ring are closed.
pub fn is_closed(&self) -> bool {
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe consider moving some of these definitions to impl RingData?

@@ -0,0 +1,66 @@
/// Owns a reference to a shared memory region.
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmmmm I don't quite understand "owning a reference to a shared memory region". Unless we do something when the reference count hits 0, this comment doesn't really make sense...

len: u64,
}

impl SharedMemoryRegion {
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

...and this is also not quite about shared too...

/// Caller must ensure the region is zero-initialized before the first side
/// is constructed, and that exactly one `Side::A` and one `Side::B` are
/// created per region.
pub fn new(region: &'a SharedMemoryRegion, ring_size: u64, side: Side) -> Self {
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Given that the SharedMemoryRegion right now doesn't really "own" the memory, the reference here also don't quite make sense to me...if the concern is that it may have different implementation on the vmm side and the Arca side, we could keep it as a trait here, and let the BidirectionalPipe own it? Then on the vmm-side, this would be mmap::Mmap, on the Arca-side, it holds a raw pointer and size and does nothing on Drop?

}

/// Signal that this consumer will read no more bytes.
pub fn close_reader(&self) {
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this be &mut self since there could only be one reader?

}

/// Close this side's outgoing (write) direction.
pub fn close_write(&self) {
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also these functions should also be &mut self? If the user want to be able to handle the consumer and producer side independently, they should split.

@yhdengh yhdengh changed the title Feat: bidirectional pipe feat: bidirectional pipe Jun 6, 2026
}

impl<'a> traits::Write for RingProducer<'a> {
fn write(&mut self, buf: &[u8]) -> Result<usize, PipeError> {
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the logic of "closing the read-end when read EOF" and "closing the write-end when the read-end closed prematurely" should happen at RingProducer and RingConsumer level, or BidirectionalPipe, instead of SyncStream

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant