-
Notifications
You must be signed in to change notification settings - Fork 37
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add Safe Abstractions for FuriStreamBuffer
#177
Add Safe Abstractions for FuriStreamBuffer
#177
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The API looks great. Here is the first iteration of nitpicking, but generally the PR looks super accurate
crates/flipperzero/src/furi/mod.rs
Outdated
#[cfg(feature = "alloc")] | ||
pub mod stream_buffer; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure about the following point, but I would prefer a separate stream-buffer
feature which depends on alloc
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It feels really bloated to a feature just because of the Arc
I used. I could replace it with some custom counting logic using an AtomicUsize
and sys::malloc
to get a pointer but I'm not sure if that is better.
} | ||
} | ||
|
||
unsafe impl Send for Receiver {} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same here
It will take me some time to think on the |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi @cptpiepmatz!
Thanks for the PR! I really like the Sender
/ Receiver
concept and how extensively you've documented everything 💖.
I think it would be useful to expose the low-level StreamBuffer
API for no-alloc
cases, but that's something we can certainly expose after merging this PR. Vast majority of comments are just little things for consistency with the other parts of the flipperzero-rs
API.
/// | ||
/// In an interrupt routine, this method behaves like [`send`](Self::send). | ||
pub fn send_with_timeout(&self, data: &[u8], timeout: core::time::Duration) -> usize { | ||
let timeout = sys::furi::duration_to_ticks(timeout); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For the furi
APIs we generally use furi::Duration
rather than core::time::Duration
to provide tick-level control over the timeout**.
(** Though we should really implement From/TryFrom<core::time::Duration>
for furi::Duration
)
I made the The Since the |
Hi @cptpiepmatz. This looks great! I'd be happy to merge this once @JarvisCraft has taken a final look. |
@dcoles could you please approve the workflow again? I added a |
@JarvisCraft is this ready to merge? |
Hi there, apologies for the long reply. I will take a look at the PR this week. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Apologies for the delay on code-review.
The PR looks amazing and the detailed docs are just the chef's kiss.
Thanks a lot for your contribution <3
#[cfg_attr(feature = "alloc", doc = "[`into_stream`](Self::into_stream)")] | ||
/// which is available using the `alloc` feature. | ||
pub fn new(size: NonZeroUsize, trigger_level: usize) -> Self { | ||
let size: usize = size.into(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Non-blocker nit (ptobably, for the future changes): given that type annotation is already used, from
seems more appropriate:
let size: usize = size.into(); | |
let size = usize::from(size); |
use core::{cell::Cell, marker::PhantomData}; | ||
|
||
/// A zero-sized type used to mark types as `!Sync`. | ||
type PhantomUnsync = PhantomData<Cell<()>>; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For future work on our side: this should probably be moved to some internal utils
module
Squashed the commits so that |
Sweet! |
Hey 👋🏻,
In this PR, I added some safe abstractions for the
FuriStreamBuffer
.While working on it, I came across this note in the stream buffer implementation:
So, I figured, why not enforce this constraint in the type system? The result is a split into a sender and receiver, similar to the
mpsc
channel in the standard library. They implementSend
, so they can be moved between threads, but notClone
orSync
, making sure we only have one of each in a pair. Unfortunately, I had to useArc
to give ownership to both sides, which means this requiresalloc
. Other than that, I’m happy with how the API turned out.I also added an example where data is sent between different threads.