avm2: Use `Gc` instead of `GcCell` in `SoundObject`

This commit is contained in:
Lord-McSweeney 2024-07-31 10:03:33 -07:00 committed by Lord-McSweeney
parent 4773591c42
commit 458264a76a
2 changed files with 40 additions and 28 deletions

View File

@ -1392,7 +1392,7 @@ impl<'gc> Object<'gc> {
Self::LoaderInfoObject(o) => WeakObject::LoaderInfoObject(LoaderInfoObjectWeak(GcCell::downgrade(o.0))),
Self::ClassObject(o) => WeakObject::ClassObject(ClassObjectWeak(Gc::downgrade(o.0))),
Self::VectorObject(o) => WeakObject::VectorObject(VectorObjectWeak(Gc::downgrade(o.0))),
Self::SoundObject(o) => WeakObject::SoundObject(SoundObjectWeak(GcCell::downgrade(o.0))),
Self::SoundObject(o) => WeakObject::SoundObject(SoundObjectWeak(Gc::downgrade(o.0))),
Self::SoundChannelObject(o) => WeakObject::SoundChannelObject(SoundChannelObjectWeak(GcCell::downgrade(o.0))),
Self::BitmapDataObject(o) => WeakObject::BitmapDataObject(BitmapDataObjectWeak(Gc::downgrade(o.0))),
Self::DateObject(o) => WeakObject::DateObject(DateObjectWeak(Gc::downgrade(o.0))),

View File

@ -12,7 +12,11 @@ use crate::context::UpdateContext;
use crate::display_object::SoundTransform;
use crate::string::AvmString;
use core::fmt;
use gc_arena::{Collect, GcCell, GcWeakCell, Mutation};
use gc_arena::barrier::unlock;
use gc_arena::{
lock::{Lock, RefLock},
Collect, Gc, GcWeak, Mutation,
};
use id3::{Tag, TagLike};
use std::cell::{Ref, RefMut};
use std::io::Cursor;
@ -25,16 +29,16 @@ pub fn sound_allocator<'gc>(
class: ClassObject<'gc>,
activation: &mut Activation<'_, 'gc>,
) -> Result<Object<'gc>, Error<'gc>> {
let base = ScriptObjectData::new(class);
let base = ScriptObjectData::new(class).into();
Ok(SoundObject(GcCell::new(
Ok(SoundObject(Gc::new(
activation.context.gc_context,
SoundObjectData {
base,
sound_data: SoundData::NotLoaded {
sound_data: RefLock::new(SoundData::NotLoaded {
queued_plays: Vec::new(),
},
id3: None,
}),
id3: Lock::new(None),
},
))
.into())
@ -42,16 +46,16 @@ pub fn sound_allocator<'gc>(
#[derive(Clone, Collect, Copy)]
#[collect(no_drop)]
pub struct SoundObject<'gc>(pub GcCell<'gc, SoundObjectData<'gc>>);
pub struct SoundObject<'gc>(pub Gc<'gc, SoundObjectData<'gc>>);
#[derive(Clone, Collect, Copy, Debug)]
#[collect(no_drop)]
pub struct SoundObjectWeak<'gc>(pub GcWeakCell<'gc, SoundObjectData<'gc>>);
pub struct SoundObjectWeak<'gc>(pub GcWeak<'gc, SoundObjectData<'gc>>);
impl fmt::Debug for SoundObject<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("SoundObject")
.field("ptr", &self.0.as_ptr())
.field("ptr", &Gc::as_ptr(self.0))
.finish()
}
}
@ -60,13 +64,13 @@ impl fmt::Debug for SoundObject<'_> {
#[collect(no_drop)]
pub struct SoundObjectData<'gc> {
/// Base script object
base: ScriptObjectData<'gc>,
base: RefLock<ScriptObjectData<'gc>>,
/// The sound this object holds.
sound_data: SoundData<'gc>,
sound_data: RefLock<SoundData<'gc>>,
/// ID3Info Object
id3: Option<Object<'gc>>,
id3: Lock<Option<Object<'gc>>>,
}
#[derive(Collect)]
@ -94,10 +98,10 @@ pub struct QueuedPlay<'gc> {
impl<'gc> SoundObject<'gc> {
pub fn sound_handle(self) -> Option<SoundHandle> {
let this = self.0.read();
match this.sound_data {
let sound_data = self.0.sound_data.borrow();
match &*sound_data {
SoundData::NotLoaded { .. } => None,
SoundData::Loaded { sound } => Some(sound),
SoundData::Loaded { sound } => Some(*sound),
}
}
@ -107,8 +111,13 @@ impl<'gc> SoundObject<'gc> {
queued: QueuedPlay<'gc>,
activation: &mut Activation<'_, 'gc>,
) -> Result<bool, Error<'gc>> {
let mut this = self.0.write(activation.context.gc_context);
match &mut this.sound_data {
let mut sound_data = unlock!(
Gc::write(activation.context.gc_context, self.0),
SoundObjectData,
sound_data
)
.borrow_mut();
match &mut *sound_data {
SoundData::NotLoaded { queued_plays } => {
queued_plays.push(queued);
// We don't know the length yet, so return the `SoundChannel`
@ -123,14 +132,19 @@ impl<'gc> SoundObject<'gc> {
context: &mut UpdateContext<'_, 'gc>,
sound: SoundHandle,
) -> Result<(), Error<'gc>> {
let mut this = self.0.write(context.gc_context);
let mut sound_data = unlock!(
Gc::write(context.gc_context, self.0),
SoundObjectData,
sound_data
)
.borrow_mut();
let mut activation = Activation::from_nothing(context.reborrow());
match &mut this.sound_data {
match &mut *sound_data {
SoundData::NotLoaded { queued_plays } => {
for queued in std::mem::take(queued_plays) {
play_queued(queued, sound, &mut activation)?;
}
this.sound_data = SoundData::Loaded { sound };
*sound_data = SoundData::Loaded { sound };
}
SoundData::Loaded { sound: old_sound } => {
panic!("Tried to replace sound {old_sound:?} with {sound:?}")
@ -140,13 +154,11 @@ impl<'gc> SoundObject<'gc> {
}
pub fn id3(self) -> Option<Object<'gc>> {
let this = self.0.read();
this.id3
self.0.id3.get()
}
pub fn set_id3(self, mc: &Mutation<'gc>, id3: Option<Object<'gc>>) {
let mut this = self.0.write(mc);
this.id3 = id3;
unlock!(Gc::write(mc, self.0), SoundObjectData, id3).set(id3);
}
pub fn read_and_call_id3_event(self, activation: &mut Activation<'_, 'gc>, bytes: &[u8]) {
@ -265,15 +277,15 @@ fn play_queued<'gc>(
impl<'gc> TObject<'gc> for SoundObject<'gc> {
fn base(&self) -> Ref<ScriptObjectData<'gc>> {
Ref::map(self.0.read(), |read| &read.base)
self.0.base.borrow()
}
fn base_mut(&self, mc: &Mutation<'gc>) -> RefMut<ScriptObjectData<'gc>> {
RefMut::map(self.0.write(mc), |write| &mut write.base)
unlock!(Gc::write(mc, self.0), SoundObjectData, base).borrow_mut()
}
fn as_ptr(&self) -> *const ObjectPtr {
self.0.as_ptr() as *const ObjectPtr
Gc::as_ptr(self.0) as *const ObjectPtr
}
fn value_of(&self, _mc: &Mutation<'gc>) -> Result<Value<'gc>, Error<'gc>> {