Skip to content

Commit

Permalink
Tracks: Replace RwLock<TypeMap> data store with Arc<dyn Any> (#219)
Browse files Browse the repository at this point in the history
  • Loading branch information
GnomedDev authored and FelixMcFelix committed Feb 26, 2024
1 parent 535053c commit 80d9627
Show file tree
Hide file tree
Showing 4 changed files with 44 additions and 31 deletions.
2 changes: 0 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,6 @@ tracing = { version = "0.1", features = ["log"] }
tracing-futures = "0.2"
twilight-gateway = { default-features = false, optional = true, version = "0.15.0" }
twilight-model = { default-features = false, optional = true, version = "0.15.0" }
typemap_rev = { optional = true, version = "0.3" }
url = { optional = true, version = "2" }
uuid = { features = ["v4"], optional = true, version = "1" }

Expand Down Expand Up @@ -101,7 +100,6 @@ driver = [
"dep:tokio",
"dep:tokio-tungstenite",
"dep:tokio-util",
"dep:typemap_rev",
"dep:url",
"dep:uuid",
"tokio?/fs",
Expand Down
2 changes: 0 additions & 2 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -111,8 +111,6 @@ mod ws;
pub use discortp as packet;
#[cfg(feature = "driver")]
pub use serenity_voice_model as model;
#[cfg(feature = "driver")]
pub use typemap_rev as typemap;

// Re-export serde-json APIs locally to minimise conditional config elsewhere.
#[cfg(not(feature = "simd-json"))]
Expand Down
43 changes: 21 additions & 22 deletions src/tracks/handle.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
use super::*;
use crate::events::{Event, EventData, EventHandler};
use flume::{Receiver, Sender};
use std::{fmt, sync::Arc, time::Duration};
use tokio::sync::RwLock;
use typemap_rev::TypeMap;
use std::{any::Any, sync::Arc, time::Duration};
use uuid::Uuid;

#[derive(Clone, Debug)]
Expand All @@ -19,32 +17,27 @@ pub struct TrackHandle {
inner: Arc<InnerHandle>,
}

#[derive(Debug)]
struct InnerHandle {
command_channel: Sender<TrackCommand>,
uuid: Uuid,
typemap: RwLock<TypeMap>,
}

impl fmt::Debug for InnerHandle {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("InnerHandle")
.field("command_channel", &self.command_channel)
.field("uuid", &self.uuid)
.field("typemap", &"<LOCK>")
.finish()
}
data: Arc<dyn Any + Send + Sync + 'static>,
}

impl TrackHandle {
/// Creates a new handle, using the given command sink.
///
/// [`Input`]: crate::input::Input
#[must_use]
pub(crate) fn new(command_channel: Sender<TrackCommand>, uuid: Uuid) -> Self {
pub(crate) fn new(
command_channel: Sender<TrackCommand>,
uuid: Uuid,
data: Arc<dyn Any + Send + Sync + 'static>,
) -> Self {
let inner = Arc::new(InnerHandle {
command_channel,
uuid,
typemap: RwLock::new(TypeMap::new()),
data,
});

Self { inner }
Expand Down Expand Up @@ -198,16 +191,22 @@ impl TrackHandle {
self.inner.uuid
}

/// Allows access to this track's attached [`TypeMap`].
/// Allows access to this track's attached Data.
///
/// [`TypeMap`]s allow additional, user-defined data shared by all handles
/// Data allows additional, user-defined data shared by all handles
/// to be attached to any track.
///
/// Driver code will never attempt to lock access to this map,
/// preventing deadlock/stalling.
/// # Panics
/// This method will panic if the Data has not been initialised, or the type
/// provided does not equal the type passed to [`Track::new_with_data`].
#[must_use]
pub fn typemap(&self) -> &RwLock<TypeMap> {
&self.inner.typemap
pub fn data<Data>(&self) -> Arc<Data>
where
Data: Send + Sync + 'static,
{
Arc::clone(&self.inner.data)
.downcast()
.expect("TrackHandle::data generic does not match type set in TrackHandle::set_data")
}

#[inline]
Expand Down
28 changes: 23 additions & 5 deletions src/tracks/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ pub use self::{
pub(crate) use command::*;

use crate::{constants::*, driver::tasks::message::*, events::EventStore, input::Input};
use std::time::Duration;
use std::{any::Any, sync::Arc, time::Duration};
use uuid::Uuid;

/// Initial state for audio playback.
Expand Down Expand Up @@ -104,27 +104,45 @@ pub struct Track {
///
/// Defaults to a random 128-bit number.
pub uuid: Uuid,

/// Any data to be associated with the track.
pub user_data: Arc<dyn Any + Send + Sync>,
}

impl Track {
/// Create a new track directly from an [`Input`] and a random [`Uuid`].
#[must_use]
pub fn new(input: Input) -> Self {
let uuid = Uuid::new_v4();

Self::new_with_uuid(input, uuid)
Self::new_with_uuid(input, Uuid::new_v4())
}

/// Create a new track directly from an [`Input`] with a custom [`Uuid`].
#[must_use]
pub fn new_with_uuid(input: Input, uuid: Uuid) -> Self {
Self::new_with_uuid_and_data(input, uuid, Arc::new(()))
}

/// Create a new track directly from an [`Input`], user data to be associated with the track, and a random [`Uuid`].
#[must_use]
pub fn new_with_data(input: Input, user_data: Arc<dyn Any + Send + Sync + 'static>) -> Self {
Self::new_with_uuid_and_data(input, Uuid::new_v4(), user_data)
}

/// Create a new track directly from an [`Input`], user data to be associated with the track, and a custom [`Uuid`].
#[must_use]
pub fn new_with_uuid_and_data(
input: Input,
uuid: Uuid,
user_data: Arc<dyn Any + Send + Sync + 'static>,
) -> Self {
Self {
playing: PlayMode::default(),
volume: 1.0,
input,
events: EventStore::new_local(),
loops: LoopState::Finite(0),
uuid,
user_data,
}
}

Expand Down Expand Up @@ -180,7 +198,7 @@ impl Track {

pub(crate) fn into_context(self) -> (TrackHandle, TrackContext) {
let (tx, receiver) = flume::unbounded();
let handle = TrackHandle::new(tx, self.uuid);
let handle = TrackHandle::new(tx, self.uuid, self.user_data.clone());

let context = TrackContext {
handle: handle.clone(),
Expand Down

0 comments on commit 80d9627

Please sign in to comment.