Skip to content

Commit

Permalink
sndio: avoid unsafe impl Sync on InnerState
Browse files Browse the repository at this point in the history
  • Loading branch information
AaronM04 committed Nov 12, 2020
1 parent 2e0c63b commit d426f69
Show file tree
Hide file tree
Showing 2 changed files with 18 additions and 16 deletions.
20 changes: 11 additions & 9 deletions src/host/sndio/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -113,12 +113,16 @@ impl Iterator for Devices {
}
}

struct SioHdl(*mut sndio_sys::sio_hdl);

unsafe impl Send for SioHdl {}

/// The shared state between Device and Stream. Responsible for closing handle when dropped.
struct InnerState {
/// If device has been open with sio_open, contains a handle. Note that even though this is a
/// pointer type and so doesn't follow Rust's borrowing rules, we should be careful not to copy
/// it out because that may render Mutex<InnerState> ineffective in enforcing exclusive access.
hdl: Option<*mut sndio_sys::sio_hdl>,
hdl: Option<SioHdl>,

/// Buffer overrun/underrun behavior -- ignore/sync/error?
behavior: BufferXrunBehavior,
Expand Down Expand Up @@ -159,8 +163,6 @@ struct OutputCallbacks {
error_callback: Box<dyn FnMut(StreamError) + Send + 'static>,
}

unsafe impl Send for InnerState {}

#[derive(Debug, Copy, Clone, Eq, PartialEq)]
enum Status {
/// Initial state. No thread running. Device/Stream methods will start thread and change this
Expand Down Expand Up @@ -205,7 +207,7 @@ impl InnerState {
if hdl.is_null() {
return Err(SndioError::DeviceNotAvailable);
}
self.hdl = Some(hdl);
self.hdl = Some(SioHdl(hdl));

let mut sample_rate_to_par = HashMap::new();
for rate in SUPPORTED_SAMPLE_RATES {
Expand Down Expand Up @@ -267,7 +269,7 @@ impl InnerState {
// will wait for playback data to be provided (using the sio_write()
// function). Once enough data is queued to ensure that play buffers will
// not underrun, actual playback is started automatically."
sndio_sys::sio_start(self.hdl.unwrap()) // Unwrap OK because of check above
sndio_sys::sio_start(self.hdl.as_ref().unwrap().0) // Unwrap OK because of check above
};
if status != 1 {
return Err(backend_specific_error("failed to start stream"));
Expand All @@ -286,7 +288,7 @@ impl InnerState {
// playback. If samples to play are queued but playback hasn't started yet then
// playback is forced immediately; playback will actually stop once the buffer is
// drained. In no case are samples in the play buffer discarded.
sndio_sys::sio_stop(self.hdl.unwrap()) // Unwrap OK because of check above
sndio_sys::sio_stop(self.hdl.as_ref().unwrap().0) // Unwrap OK because of check above
};
if status != 1 {
return Err(backend_specific_error("error calling sio_stop"));
Expand Down Expand Up @@ -385,7 +387,7 @@ impl InnerState {

let status = unsafe {
// Retrieve the actual parameters of the device.
sndio_sys::sio_getpar(self.hdl.unwrap(), par as *mut _)
sndio_sys::sio_getpar(self.hdl.as_ref().unwrap().0, par as *mut _)
};
if status != 1 {
return Err(backend_specific_error(
Expand Down Expand Up @@ -439,7 +441,7 @@ impl InnerState {
let status = unsafe {
// Request the device using our parameters
// unwrap OK because of the check at the top of this function.
sndio_sys::sio_setpar(self.hdl.unwrap(), &mut newpar as *mut _)
sndio_sys::sio_setpar(self.hdl.as_ref().unwrap().0, &mut newpar as *mut _)
};
if status != 1 {
return Err(backend_specific_error("failed to set parameters with sio_setpar").into());
Expand All @@ -452,7 +454,7 @@ impl Drop for InnerState {
fn drop(&mut self) {
if let Some(hdl) = self.hdl.take() {
unsafe {
sndio_sys::sio_close(hdl);
sndio_sys::sio_close(hdl.0);
}
}
}
Expand Down
14 changes: 7 additions & 7 deletions src/host/sndio/runner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ pub(super) fn runner(inner_state_arc: Arc<Mutex<InnerState>>) {
paused = false;
}
nfds = unsafe {
sndio_sys::sio_nfds(inner_state.hdl.unwrap()) // Unwrap OK because of open call above
sndio_sys::sio_nfds(inner_state.hdl.as_ref().unwrap().0) // Unwrap OK because of open call above
};
if nfds <= 0 {
inner_state.error(backend_specific_error(format!(
Expand All @@ -133,7 +133,7 @@ pub(super) fn runner(inner_state_arc: Arc<Mutex<InnerState>>) {
// Populate pollfd structs with sndio_sys::sio_pollfd
nfds = unsafe {
sndio_sys::sio_pollfd(
inner_state.hdl.unwrap(), // Unwrap OK because of open call above
inner_state.hdl.as_ref().unwrap().0, // Unwrap OK because of open call above
pollfds.as_mut_ptr(),
(libc::POLLOUT | libc::POLLIN) as i32,
)
Expand Down Expand Up @@ -162,9 +162,9 @@ pub(super) fn runner(inner_state_arc: Arc<Mutex<InnerState>>) {
{
let mut inner_state = inner_state_arc.lock().unwrap();
// Unwrap OK because of open call above
revents =
unsafe { sndio_sys::sio_revents(inner_state.hdl.unwrap(), pollfds.as_mut_ptr()) }
as i16;
revents = unsafe {
sndio_sys::sio_revents(inner_state.hdl.as_ref().unwrap().0, pollfds.as_mut_ptr())
} as i16;
if revents & libc::POLLHUP != 0 {
inner_state.error(backend_specific_error("device disappeared"));
break;
Expand Down Expand Up @@ -222,7 +222,7 @@ pub(super) fn runner(inner_state_arc: Arc<Mutex<InnerState>>) {
// unwrap OK because .open was called
let bytes_written = unsafe {
sndio_sys::sio_write(
inner_state.hdl.unwrap(),
inner_state.hdl.as_ref().unwrap().0,
(output_data.data as *const u8).add(output_offset_bytes_into_buf as usize)
as *const _,
data_byte_size as u64 - output_offset_bytes_into_buf,
Expand Down Expand Up @@ -271,7 +271,7 @@ pub(super) fn runner(inner_state_arc: Arc<Mutex<InnerState>>) {
// unwrap OK because .open was called
let bytes_read = unsafe {
sndio_sys::sio_read(
inner_state.hdl.unwrap(),
inner_state.hdl.as_ref().unwrap().0,
(input_data.data as *const u8).add(input_offset_bytes_into_buf as usize)
as *mut _,
data_byte_size as u64 - input_offset_bytes_into_buf,
Expand Down

0 comments on commit d426f69

Please sign in to comment.