Skip to content
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

fix: Allow more flexible EventStream buffers #124

Merged

Conversation

hawkw
Copy link
Contributor

@hawkw hawkw commented Jan 25, 2019

This commit changes the EventStream type to hopefully avoid some of
the previously observed difficulties (viz. #120) around the lifetime of
the user-provided buffer.

Previously, calls to EventStream::new were required to provide an
&'a mut [u8], where the EventStream is generic over the lifetime
'a. This is an issue in many cases, where the EventStream must
live for the 'static lifetime, as it requires a 'static mut buffer,
which is difficult to create safely.

This branch changes the EventStream type to be generic over a type
T which implements AsRef<[u8]> and AsMut<[u8]>. Since an
&mut [u8] implements these traits, means that the EventStream may
now be constructed with an owned buffer or a borrowed buffer. Thus,
users can pass in a &mut [u8] to a short-lived EventStream, while a
'static one can be constructed by passing in a [u8; N], a
Vec<u8>, or a &'static mut [u8].

Additionally, this means that buffer types from other crates (such as
bytes) could theoretically be used, without requiring inotify to
depend on those crates. I'm not sure if this would actually happen that
often in practice, but it's a nice side benefit.

Fixes #120.

Signed-off-by: Eliza Weisman eliza@buoyant.io

This commit changes the `EventStream` type to hopefully avoid some of
the previously observed difficulties (viz. hannobraun#120) around the lifetime of
the user-provided buffer.

Previously, calls to `EventStream::new` were required to provide an
`&'a mut [u8]`, where the `EventStream` is generic over the lifetime
`'a`. This is an issue in many cases, where the `EventStream` must
live for the `'static` lifetime, as it requires a `'static mut` buffer,
which is difficult to create safely.

This branch changes the `EventStream` type to be generic over a type
`T` which implements `AsRef<[u8]>` and `AsMut<[u8]>`. Since an
`&mut [u8]` implements these traits, means that the `EventStream` may
now be constructed with an owned buffer _or_ a borrowed buffer. Thus,
users can pass in a `&mut [u8]` to a short-lived `EventStream`, while a
`'static` one can be constructed by passing in a `[u8; N]`, a
`Vec<u8>`, _or_ a `&'static mut [u8]`.

Additionally, this means that buffer types from other crates (such as
`bytes`) could theoretically be used, without requiring `inotify` to
depend on those crates. I'm not sure if this would actually happen that
often in practice, but it's a nice side benefit.

Fixes hannobraun#120.

Signed-off-by: Eliza Weisman <eliza@buoyant.io>
Copy link
Owner

@hannobraun hannobraun left a comment

Choose a reason for hiding this comment

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

I love it!

I haven't tested this thoroughly, to make sure it's strictly better than the previous API, but:

So I'm confident merging this. Thank you @hawkw!

@@ -26,7 +22,7 @@ fn main() -> Result<(), io::Error> {
});

let future = inotify
.event_stream(unsafe { &mut BUFFER })
Copy link
Owner

Choose a reason for hiding this comment

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

I think this example should be removed and this technique here should be part of the API documentation (as a small example). Not necessary to do it in this PR, but we shouldn't forget to open an issue, at least.

@@ -61,7 +61,7 @@ fn it_should_watch_a_file_async() {

use futures::Stream;
let events = inotify
.event_stream(&mut buffer)
.event_stream(&mut buffer[..])
Copy link
Owner

Choose a reason for hiding this comment

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

I assume this change was required to get it to compile? If so, this is a breaking change. Not a problem, just want to confirm.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeah, that's correct --- it's only necessary when the array is longer than [T; 32], as only arrays of length 0-32 have AsRef/AsMut impls.

@hannobraun hannobraun merged commit f78ed97 into hannobraun:master Jan 28, 2019
@hannobraun
Copy link
Owner

@hawkw
Since you seem to be using this in production, would you like me to do a new (minor) release right now?

I'd prefer to let this sit for a while, due to laziness/busyness, to let it mature for a bit, and potentially to group it with other breaking changes that might be coming. But I'm happy to cut a release right now, if that helps you out.

@hawkw
Copy link
Contributor Author

hawkw commented Jan 28, 2019

@hannobraun if you're anticipating more breaking changes in the near future, I think we're fine with a Git dependency temporarily.

Alternatively, I think it may be possible to make the change more backwards-compatible, by adding a new constructor that takes a T: AsRef + AsMut, leaving new's signature as it was previously, and having it slice the buffer and pass it to the new constructor. However, I think this is probably not a great idea, as it results in a more confusing API, and the EventStream type's generic parameter is still changing, so this is still a breaking change when the EventStream is e.g. a struct field...

@hannobraun
Copy link
Owner

@hawkw I'm not anticipating more breaking changes, I just figured we might decrease some churn in case any more are coming. Sounds like a new release is the way to go though. I'll try to get it done soon.

I agree that attempts to alleviate the breakage are probably counter-productive, for the reasons you mentioned.

hawkw added a commit to linkerd/linkerd2-proxy that referenced this pull request Feb 1, 2019
Since my PR against inotify (hannobraun/inotify-rs#124) has merged, we can
go back to depending on the upstream version. Also, this updates the SHA
we depend on to one that actually exists.

Signed-off-by: Eliza Weisman <eliza@buoyant.io>
hawkw added a commit to linkerd/linkerd2-proxy that referenced this pull request Feb 1, 2019
Since my PR against `inotify` (hannobraun/inotify-rs#124) has merged, we can
go back to depending on the upstream version. Also, this updates the SHA
we depend on to one that actually exists, which should fix the build.

I've also removed the `inotify` dependency from the main proxy crate's
`Cargo.toml.` This dependency is not actually used, as the `fs-watch` lib
crate fully encapsulates the dependency. I think that this was overlooked
when factoring out `fs-watch` into its own crate.

It seems better to not specify the same dependency in multiple places,
especially since we're not using one of them.

Signed-off-by: Eliza Weisman <eliza@buoyant.io>
panthervis added a commit to panthervis/linkerd2-proxy that referenced this pull request Oct 8, 2021
Since my PR against `inotify` (hannobraun/inotify-rs#124) has merged, we can
go back to depending on the upstream version. Also, this updates the SHA
we depend on to one that actually exists, which should fix the build.

I've also removed the `inotify` dependency from the main proxy crate's
`Cargo.toml.` This dependency is not actually used, as the `fs-watch` lib
crate fully encapsulates the dependency. I think that this was overlooked
when factoring out `fs-watch` into its own crate.

It seems better to not specify the same dependency in multiple places,
especially since we're not using one of them.

Signed-off-by: Eliza Weisman <eliza@buoyant.io>
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.

None yet

2 participants