queue: cache device FD into inner struct
diff --git a/src/device/queue.rs b/src/device/queue.rs
index 70e1c5f..6347283 100644
--- a/src/device/queue.rs
+++ b/src/device/queue.rs
@@ -40,10 +40,20 @@
/// the `Device`.
pub struct QueueBase {
device: Rc<Device>,
+ /// Fd of the device, for faster access since it can be shared. This is
+ /// guaranteed to remain valid as long as the device is alive, and we are
+ /// keeping a refcounted reference to it.
+ fd: RawFd,
type_: QueueType,
capabilities: ioctl::BufferCapabilities,
}
+impl AsRawFd for QueueBase {
+ fn as_raw_fd(&self) -> RawFd {
+ self.fd
+ }
+}
+
impl<'a> Drop for QueueBase {
/// Make the queue available again.
fn drop(&mut self) {
@@ -66,12 +76,6 @@
state: S,
}
-impl AsRawFd for QueueBase {
- fn as_raw_fd(&self) -> RawFd {
- self.device.fd.borrow().as_raw_fd()
- }
-}
-
/// Methods of `Queue` that are available no matter the state.
impl<D, S> Queue<D, S>
where
@@ -87,16 +91,17 @@
}
pub fn get_format(&self) -> Result<Format> {
- ioctl::g_fmt(&*self.inner.device.fd.borrow(), self.inner.type_)
+ ioctl::g_fmt(&self.inner, self.inner.type_)
}
/// This method can invalidate any current format iterator, hence it requires
/// the queue to be mutable. This way of doing is not perfect though, as setting
/// the format on one queue can change the options available on another.
pub fn set_format(&mut self, format: Format) -> Result<Format> {
+ let type_ = self.inner.type_;
ioctl::s_fmt(
- &mut *self.inner.device.fd.borrow_mut(),
- self.inner.type_,
+ &mut self.inner,
+ type_,
format,
)
}
@@ -105,7 +110,7 @@
/// Useful to check what modifications need to be done to a format before it
/// can be used.
pub fn try_format(&self, format: Format) -> Result<Format> {
- ioctl::try_fmt(&*self.inner.device.fd.borrow(), self.inner.type_, format)
+ ioctl::try_fmt(&self.inner, self.inner.type_, format)
}
/// Returns a `FormatBuilder` which is set to the currently active format
@@ -130,7 +135,7 @@
impl<'a> FormatBuilder<'a> {
fn new(queue: &'a mut QueueBase) -> Result<Self> {
- let format = ioctl::g_fmt(&*queue.device.fd.borrow(), queue.type_)?;
+ let format = ioctl::g_fmt(queue, queue.type_)?;
Ok(Self { queue, format })
}
@@ -157,7 +162,7 @@
/// be returned.
pub fn apply(self) -> Result<Format> {
ioctl::s_fmt(
- &mut *self.queue.device.fd.borrow_mut(),
+ self.queue,
self.queue.type_,
self.format,
)
@@ -168,7 +173,7 @@
/// parameters after this call.
pub fn try_apply(&mut self) -> Result<()> {
let new_format = ioctl::try_fmt(
- &mut *self.queue.device.fd.borrow_mut(),
+ self.queue,
self.queue.type_,
self.format.clone(),
)?;
@@ -201,9 +206,12 @@
assert_eq!(used_queues.insert(queue_type), true);
drop(used_queues);
+ let fd = device.as_raw_fd();
+
Ok(Queue::<D, QueueInit> {
inner: QueueBase {
device,
+ fd,
type_: queue_type,
capabilities,
},
@@ -214,18 +222,18 @@
/// Allocate `count` buffers for this queue and make it transition to the
/// `BuffersAllocated` state.
- pub fn request_buffers<M: Memory>(self, count: u32) -> Result<Queue<D, BuffersAllocated<M>>> {
- // TODO use try_borrow_mut() and return an error if borrow is impossible.
+ pub fn request_buffers<M: Memory>(mut self, count: u32) -> Result<Queue<D, BuffersAllocated<M>>> {
+ let type_ = self.inner.type_;
let num_buffers: usize = ioctl::reqbufs(
- &mut *self.inner.device.fd.borrow_mut(),
- self.inner.type_,
+ &mut self.inner,
+ type_,
M::HandleType::MEMORY_TYPE,
count,
)?;
// The buffers have been allocated, now let's get their features.
let querybuf: ioctl::QueryBuffer =
- ioctl::querybuf(&*self.inner.device.fd.borrow(), self.inner.type_, 0)?;
+ ioctl::querybuf(&self.inner, self.inner.type_, 0)?;
Ok(Queue {
inner: self.inner,
@@ -241,10 +249,11 @@
}
impl<D: Direction, M: Memory> Queue<D, BuffersAllocated<M>> {
- pub fn free_buffers(self) -> Result<Queue<D, QueueInit>> {
+ pub fn free_buffers(mut self) -> Result<Queue<D, QueueInit>> {
+ let type_ = self.inner.type_;
ioctl::reqbufs(
- &mut *self.inner.device.fd.borrow_mut(),
- self.inner.type_,
+ &mut self.inner,
+ type_,
M::HandleType::MEMORY_TYPE,
0,
)?;
@@ -307,9 +316,9 @@
self.state.buffers_state.len()
}
- pub fn streamon(&self) -> Result<()> {
- // TODO use try_borrow_mut() and return an error if borrow is impossible.
- ioctl::streamon(&mut *self.inner.device.fd.borrow_mut(), self.inner.type_)
+ pub fn streamon(&mut self) -> Result<()> {
+ let type_ = self.inner.type_;
+ ioctl::streamon(&mut self.inner, type_)
}
/// Stop streaming on this queue.
@@ -318,7 +327,8 @@
/// dequeued yet return to the `Free` state. Buffer references obtained via
/// `dequeue()` remain valid.
pub fn streamoff(&mut self) -> Result<Vec<CanceledBuffer<M>>> {
- ioctl::streamoff(&mut *self.inner.device.fd.borrow_mut(), self.inner.type_)?;
+ let type_ = self.inner.type_;
+ ioctl::streamoff(&mut self.inner, type_)?;
let canceled_buffers = self
.state
@@ -350,7 +360,7 @@
}
pub fn query_buffer(&self, id: usize) -> Result<ioctl::QueryBuffer> {
- ioctl::querybuf(&*self.inner.device.fd.borrow(), self.inner.type_, id)
+ ioctl::querybuf(&self.inner, self.inner.type_, id)
}
// Take buffer `id` in order to prepare it for queueing, provided it is available.
@@ -381,7 +391,7 @@
/// The data in the `DQBuffer` is read-only.
pub fn dequeue(&self) -> Result<DQBuffer<M>> {
let dqbuf: ioctl::DQBuffer =
- ioctl::dqbuf(&*self.inner.device.fd.borrow(), self.inner.type_)?;
+ ioctl::dqbuf(&self.inner, self.inner.type_)?;
let id = dqbuf.index as usize;
// The buffer will remain Dequeued until our reference to it is destroyed.
diff --git a/src/device/queue/qbuf.rs b/src/device/queue/qbuf.rs
index adbc5a6..66bfa4f 100644
--- a/src/device/queue/qbuf.rs
+++ b/src/device/queue/qbuf.rs
@@ -132,7 +132,7 @@
};
match ioctl::qbuf(
- &*self.queue.inner.device.fd.borrow(),
+ &self.queue.inner,
self.queue.inner.type_,
self.index,
self.qbuffer,