Tracks: Replace RwLock<TypeMap> data store with Arc<dyn Any> (#219)
This commit is contained in:
@@ -54,7 +54,6 @@ tracing = { version = "0.1", features = ["log"] }
|
|||||||
tracing-futures = "0.2"
|
tracing-futures = "0.2"
|
||||||
twilight-gateway = { default-features = false, optional = true, version = "0.15.0" }
|
twilight-gateway = { default-features = false, optional = true, version = "0.15.0" }
|
||||||
twilight-model = { 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" }
|
|
||||||
typenum = { optional = true, version = "1.17.0" }
|
typenum = { optional = true, version = "1.17.0" }
|
||||||
url = { optional = true, version = "2" }
|
url = { optional = true, version = "2" }
|
||||||
uuid = { features = ["v4"], optional = true, version = "1" }
|
uuid = { features = ["v4"], optional = true, version = "1" }
|
||||||
@@ -111,7 +110,6 @@ driver = [
|
|||||||
"dep:tokio",
|
"dep:tokio",
|
||||||
"dep:tokio-tungstenite",
|
"dep:tokio-tungstenite",
|
||||||
"dep:tokio-util",
|
"dep:tokio-util",
|
||||||
"dep:typemap_rev",
|
|
||||||
"dep:typenum",
|
"dep:typenum",
|
||||||
"dep:url",
|
"dep:url",
|
||||||
"dep:uuid",
|
"dep:uuid",
|
||||||
|
|||||||
@@ -112,8 +112,6 @@ mod ws;
|
|||||||
pub use discortp as packet;
|
pub use discortp as packet;
|
||||||
#[cfg(feature = "driver")]
|
#[cfg(feature = "driver")]
|
||||||
pub use serenity_voice_model as model;
|
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.
|
// Re-export serde-json APIs locally to minimise conditional config elsewhere.
|
||||||
#[cfg(not(feature = "simd-json"))]
|
#[cfg(not(feature = "simd-json"))]
|
||||||
|
|||||||
@@ -1,9 +1,8 @@
|
|||||||
use super::*;
|
use super::*;
|
||||||
use crate::events::{Event, EventData, EventHandler};
|
use crate::events::{Event, EventData, EventHandler};
|
||||||
use flume::{Receiver, Sender};
|
use flume::{Receiver, Sender};
|
||||||
use std::{fmt, sync::Arc};
|
use std::{any::Any, sync::Arc, time::Duration};
|
||||||
use tokio::sync::RwLock;
|
use uuid::Uuid;
|
||||||
use typemap_rev::TypeMap;
|
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
/// Handle for safe control of a [`Track`] from other threads, outside
|
/// Handle for safe control of a [`Track`] from other threads, outside
|
||||||
@@ -18,20 +17,11 @@ pub struct TrackHandle {
|
|||||||
inner: Arc<InnerHandle>,
|
inner: Arc<InnerHandle>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
struct InnerHandle {
|
struct InnerHandle {
|
||||||
command_channel: Sender<TrackCommand>,
|
command_channel: Sender<TrackCommand>,
|
||||||
uuid: Uuid,
|
uuid: Uuid,
|
||||||
typemap: RwLock<TypeMap>,
|
data: Arc<dyn Any + Send + Sync + 'static>,
|
||||||
}
|
|
||||||
|
|
||||||
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()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TrackHandle {
|
impl TrackHandle {
|
||||||
@@ -39,11 +29,15 @@ impl TrackHandle {
|
|||||||
///
|
///
|
||||||
/// [`Input`]: crate::input::Input
|
/// [`Input`]: crate::input::Input
|
||||||
#[must_use]
|
#[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 {
|
let inner = Arc::new(InnerHandle {
|
||||||
command_channel,
|
command_channel,
|
||||||
uuid,
|
uuid,
|
||||||
typemap: RwLock::new(TypeMap::new()),
|
data,
|
||||||
});
|
});
|
||||||
|
|
||||||
Self { inner }
|
Self { inner }
|
||||||
@@ -197,16 +191,22 @@ impl TrackHandle {
|
|||||||
self.inner.uuid
|
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.
|
/// to be attached to any track.
|
||||||
///
|
///
|
||||||
/// Driver code will never attempt to lock access to this map,
|
/// # Panics
|
||||||
/// preventing deadlock/stalling.
|
/// 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]
|
#[must_use]
|
||||||
pub fn typemap(&self) -> &RwLock<TypeMap> {
|
pub fn data<Data>(&self) -> Arc<Data>
|
||||||
&self.inner.typemap
|
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]
|
#[inline]
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ pub use self::{
|
|||||||
pub(crate) use command::*;
|
pub(crate) use command::*;
|
||||||
|
|
||||||
use crate::{constants::*, driver::tasks::message::*, events::EventStore, input::Input};
|
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;
|
use uuid::Uuid;
|
||||||
|
|
||||||
/// Initial state for audio playback.
|
/// Initial state for audio playback.
|
||||||
@@ -104,20 +104,37 @@ pub struct Track {
|
|||||||
///
|
///
|
||||||
/// Defaults to a random 128-bit number.
|
/// Defaults to a random 128-bit number.
|
||||||
pub uuid: Uuid,
|
pub uuid: Uuid,
|
||||||
|
|
||||||
|
/// Any data to be associated with the track.
|
||||||
|
pub user_data: Arc<dyn Any + Send + Sync>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Track {
|
impl Track {
|
||||||
/// Create a new track directly from an [`Input`] and a random [`Uuid`].
|
/// Create a new track directly from an [`Input`] and a random [`Uuid`].
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn new(input: Input) -> Self {
|
pub fn new(input: Input) -> Self {
|
||||||
let uuid = Uuid::new_v4();
|
Self::new_with_uuid(input, Uuid::new_v4())
|
||||||
|
|
||||||
Self::new_with_uuid(input, uuid)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a new track directly from an [`Input`] with a custom [`Uuid`].
|
/// Create a new track directly from an [`Input`] with a custom [`Uuid`].
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn new_with_uuid(input: Input, uuid: Uuid) -> Self {
|
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 {
|
Self {
|
||||||
playing: PlayMode::default(),
|
playing: PlayMode::default(),
|
||||||
volume: 1.0,
|
volume: 1.0,
|
||||||
@@ -125,6 +142,7 @@ impl Track {
|
|||||||
events: EventStore::new_local(),
|
events: EventStore::new_local(),
|
||||||
loops: LoopState::Finite(0),
|
loops: LoopState::Finite(0),
|
||||||
uuid,
|
uuid,
|
||||||
|
user_data,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -180,7 +198,7 @@ impl Track {
|
|||||||
|
|
||||||
pub(crate) fn into_context(self) -> (TrackHandle, TrackContext) {
|
pub(crate) fn into_context(self) -> (TrackHandle, TrackContext) {
|
||||||
let (tx, receiver) = flume::unbounded();
|
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 {
|
let context = TrackContext {
|
||||||
handle: handle.clone(),
|
handle: handle.clone(),
|
||||||
|
|||||||
Reference in New Issue
Block a user