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

Make a device struct in charge of its own memory #8

Open
wants to merge 3 commits into
base: master
Choose a base branch
from

Conversation

lily-mara
Copy link
Contributor

@lily-mara lily-mara commented Jan 31, 2019

Currently, the lifetime of a Device is dependent on the Devices iterator that created it. I don't see a real necessity for this, other than the simplicity of implementing Drop given the hid_free_enumeration function. If we break from this function and write our own Drop that frees all of the fields manually, each Device is wholly independent, and can be owned anywhere in memory. In my use case, I need to pass a Device between threads, and this is not possible given that the Devices share the same lifetime.

Also, the hidapi maintainers have stated that the linux and Mac versions are completely thread safe, so it should be safe to mark Device as Send on those platforms.

@lily-mara
Copy link
Contributor Author

I updated the diff to re-implement Drop for the Devices iterator, because if it is left out, any Device that is not emitted from the Devices iterator will not be Droped because in Rust's view, it has never existed.

src/devices.rs Outdated Show resolved Hide resolved
src/device.rs Outdated

_marker: PhantomData,
}
pub unsafe fn new<'b>(ptr: *const hid_device_info) -> Device {
Copy link
Owner

Choose a reason for hiding this comment

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

The lifetime annotation here is not needed anymore.

src/device.rs Show resolved Hide resolved
@meh
Copy link
Owner

meh commented Apr 16, 2020

I just realized I'm very stupid and never actually sent the review, and then entirely forgot about this.

@meh
Copy link
Owner

meh commented May 26, 2020

Since you got rustfmt enabled in your editor, could you make a first commit that runs cargo fmt, and then a separate commit for your stuff?

So it's easier to review, and then everyone is happy stuff is rustfmt'd 🐼

lily-mara added a commit to lily-mara/rust-hid that referenced this pull request Jul 1, 2020
This resolves @meh's comment on meh#8
@lily-mara
Copy link
Contributor Author

Sorry for the long turn-around on this, but I ran cargo-fmt in #10

@meh
Copy link
Owner

meh commented Jul 1, 2020

Could you rebase this please?

@lily-mara
Copy link
Contributor Author

rebased, and the diff is looking much better

Copy link
Contributor

@carlosmn carlosmn left a comment

Choose a reason for hiding this comment

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

I came upon this PR after finding issues with valgrind which explain why some devices seemed to be disappearing. So here's a couple of comments from someone who's spent a long time dealing with C and interop.

}
impl Drop for Devices {
fn drop(&mut self) {
if !self.cur.is_null() {
Copy link
Contributor

Choose a reason for hiding this comment

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

This check should not be necessary as C free functions deal just fine with receiving NULL as their input, both in general and in particular hid_free_enumeration.

_marker: PhantomData,
}
pub unsafe fn new(ptr: *const hid_device_info) -> Device {
Device { ptr }
Copy link
Contributor

Choose a reason for hiding this comment

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

Since each Device is taking ownership of its node in the linked list, we should probably get rid of the value in the next pointer. Even if we don't use it when dropping the struct, my C senses are tingling.

Though GH won't let me comment on the relevant piece of code as it's context, the next function in the iterator should treat the next pointer as a Option<const * _> and do something equivalent to Option::take in order to dereference it and get the next node. This is also what you would/should do when doing the equivalent in C as we are removing the nodes from the list.

All this to say I think in next() the code should be zeroing out the next pointer before passing it to this constructor.

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.

3 participants