Skip to content

Commit

Permalink
chore: Replace generational-arena with slotmap
Browse files Browse the repository at this point in the history
  • Loading branch information
torokati44 committed Mar 2, 2024
1 parent 5b7c48e commit d59e925
Show file tree
Hide file tree
Showing 19 changed files with 82 additions and 81 deletions.
19 changes: 5 additions & 14 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ wgpu = "0.19.3"
egui = "0.26.2"
clap = { version = "4.5.1", features = ["derive"] }
anyhow = "1.0"
slotmap = "1.0.7"

[workspace.lints.rust]
# Clippy nightly often adds new/buggy lints that we want to ignore.
Expand Down
2 changes: 1 addition & 1 deletion core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ bitstream-io = "2.2.0"
flate2 = "1.0.28"
fnv = "1.0.7"
gc-arena = { package = "ruffle_gc_arena", path = "../ruffle_gc_arena" }
generational-arena = "0.2.9"
slotmap = { workspace = true }
indexmap = "2.2.5"
tracing = { workspace = true }
ruffle_render = { path = "../render", features = ["tessellator"] }
Expand Down
16 changes: 8 additions & 8 deletions core/src/backend/audio.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use crate::{
};
use downcast_rs::Downcast;
use gc_arena::Collect;
use generational_arena::{Arena, Index};
use slotmap::{DefaultKey, Key, SlotMap};

#[cfg(feature = "audio")]
pub mod decoders;
Expand Down Expand Up @@ -35,8 +35,8 @@ mod decoders {
use thiserror::Error;
use web_time::Duration;

pub type SoundHandle = Index;
pub type SoundInstanceHandle = Index;
pub type SoundHandle = DefaultKey;
pub type SoundInstanceHandle = DefaultKey;
pub type DecodeError = decoders::Error;

#[derive(Eq, PartialEq, Clone, Copy, Debug)]
Expand Down Expand Up @@ -205,14 +205,14 @@ struct NullSound {

/// Audio backend that ignores all audio.
pub struct NullAudioBackend {
sounds: Arena<NullSound>,
sounds: SlotMap<SoundHandle, NullSound>,
volume: f32,
}

impl NullAudioBackend {
pub fn new() -> NullAudioBackend {
NullAudioBackend {
sounds: Arena::new(),
sounds: SlotMap::new(),
volume: 1.0,
}
}
Expand Down Expand Up @@ -259,23 +259,23 @@ impl AudioBackend for NullAudioBackend {
_sound: SoundHandle,
_sound_info: &swf::SoundInfo,
) -> Result<SoundInstanceHandle, DecodeError> {
Ok(SoundInstanceHandle::from_raw_parts(0, 0))
Ok(SoundInstanceHandle::null())
}

fn start_stream(
&mut self,
_clip_data: crate::tag_utils::SwfSlice,
_handle: &swf::SoundStreamHead,
) -> Result<SoundInstanceHandle, DecodeError> {
Ok(SoundInstanceHandle::from_raw_parts(0, 0))
Ok(SoundInstanceHandle::null())
}

fn start_substream(
&mut self,
_stream_data: Substream,
_handle: &SoundStreamInfo,
) -> Result<SoundInstanceHandle, DecodeError> {
Ok(SoundInstanceHandle::from_raw_parts(0, 0))
Ok(SoundInstanceHandle::null())
}

fn stop_sound(&mut self, _sound: SoundInstanceHandle) {}
Expand Down
14 changes: 7 additions & 7 deletions core/src/backend/audio/mixer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use super::{SoundHandle, SoundInstanceHandle, SoundStreamInfo, SoundTransform};
use crate::backend::audio::{DecodeError, RegisterError};
use crate::buffer::Substream;
use crate::tag_utils::SwfSlice;
use generational_arena::Arena;
use slotmap::SlotMap;
use std::io::Cursor;
use std::sync::{Arc, Mutex, RwLock};
use swf::AudioCompression;
Expand Down Expand Up @@ -54,10 +54,10 @@ impl CircBuf {
// all sounds and mix the audio into an output buffer audio stream.
pub struct AudioMixer {
/// The currently registered sounds.
sounds: Arena<Sound>,
sounds: SlotMap<SoundHandle, Sound>,

/// The list of actively playing sound instances.
sound_instances: Arc<Mutex<Arena<SoundInstance>>>,
sound_instances: Arc<Mutex<SlotMap<SoundInstanceHandle, SoundInstance>>>,

/// The master volume of the audio from [0.0, 1.0].
volume: Arc<RwLock<f32>>,
Expand Down Expand Up @@ -239,8 +239,8 @@ impl AudioMixer {
/// Creates a new `AudioMixer` with the given number of channels and sample rate.
pub fn new(num_output_channels: u8, output_sample_rate: u32) -> Self {
Self {
sounds: Arena::new(),
sound_instances: Arc::new(Mutex::new(Arena::new())),
sounds: SlotMap::new(),
sound_instances: Arc::new(Mutex::new(SlotMap::new())),
volume: Arc::new(RwLock::new(1.0)),
num_output_channels,
output_sample_rate,
Expand Down Expand Up @@ -428,7 +428,7 @@ impl AudioMixer {
/// Refill the output buffer by stepping through all active sounds
/// and mixing in their output.
fn mix_audio<'a, T>(
sound_instances: &mut Arena<SoundInstance>,
sound_instances: &mut SlotMap<SoundInstanceHandle, SoundInstance>,
volume: f32,
num_channels: u8,
mut output_buffer: &mut [T],
Expand Down Expand Up @@ -724,7 +724,7 @@ impl AudioMixer {
/// to perform audio mixing on a different thread.
pub struct AudioMixerProxy {
/// The list of actively playing sound instances.
sound_instances: Arc<Mutex<Arena<SoundInstance>>>,
sound_instances: Arc<Mutex<SlotMap<SoundInstanceHandle, SoundInstance>>>,

/// The master volume of the audio from [0.0, 1.0].
volume: Arc<RwLock<f32>>,
Expand Down
43 changes: 26 additions & 17 deletions core/src/loader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,8 @@ use crate::vminterface::Instantiator;
use crate::{avm2_stub_method, avm2_stub_method_context};
use encoding_rs::UTF_8;
use gc_arena::{Collect, GcCell};
use generational_arena::{Arena, Index};
use ruffle_render::utils::{determine_jpeg_tag_format, JpegTagFormat};
use slotmap::{DefaultKey, SlotMap};
use std::borrow::Borrow;
use std::fmt;
use std::sync::{Arc, Mutex, Weak};
Expand All @@ -42,7 +42,7 @@ use swf::read::{extract_swz, read_compression_type};
use thiserror::Error;
use url::{form_urlencoded, ParseError, Url};

pub type Handle = Index;
pub type Handle = DefaultKey;

/// The depth of AVM1 movies that AVM2 loads.
const LOADER_INSERTED_AVM1_DEPTH: i32 = -0xF000;
Expand Down Expand Up @@ -224,7 +224,7 @@ impl From<crate::avm1::Error<'_>> for Error {
}

/// Holds all in-progress loads for the player.
pub struct LoadManager<'gc>(Arena<Loader<'gc>>);
pub struct LoadManager<'gc>(SlotMap<Handle, Loader<'gc>>);

unsafe impl<'gc> Collect for LoadManager<'gc> {
fn trace(&self, cc: &gc_arena::Collection) {
Expand All @@ -237,7 +237,7 @@ unsafe impl<'gc> Collect for LoadManager<'gc> {
impl<'gc> LoadManager<'gc> {
/// Construct a new `LoadManager`.
pub fn new() -> Self {
Self(Arena::new())
Self(SlotMap::new())
}

/// Add a new loader to the `LoadManager`.
Expand Down Expand Up @@ -355,15 +355,24 @@ impl<'gc> LoadManager<'gc> {
///
/// This also removes all movie loaders that have completed.
pub fn movie_clip_on_load(&mut self, queue: &mut ActionQueue<'gc>) {
let mut invalidated_loaders = vec![];

for (index, loader) in self.0.iter_mut().rev() {
if loader.movie_clip_loaded(queue) {
invalidated_loaders.push(index);
}
}

for index in invalidated_loaders {
// FIXME: This relies on the iteration order of the slotmap, which
// is not defined. The container should be replaced with something
// that preserves insertion order, such as `LinkedHashMap` -
// unfortunately that doesn't provide automatic key generation.
let mut loaders: Vec<_> = self.0.keys().collect();
// `SlotMap` doesn't provide reverse iteration, so reversing afterwards.
loaders.reverse();

// Removing the keys from `loaders` whose movie hasn't loaded yet.
loaders.retain(|handle| {
self.0
.get_mut(*handle)
.expect("valid key")
.movie_clip_loaded(queue)
});

// Cleaning up the loaders that are done.
for index in loaders {
self.0.remove(index);
}
}
Expand Down Expand Up @@ -1692,7 +1701,7 @@ impl<'gc> Loader<'gc> {
}

/// Report a movie loader start event to script code.
fn movie_loader_start(handle: Index, uc: &mut UpdateContext<'_, 'gc>) -> Result<(), Error> {
fn movie_loader_start(handle: Handle, uc: &mut UpdateContext<'_, 'gc>) -> Result<(), Error> {
let me = uc.load_manager.get_loader_mut(handle);
if me.is_none() {
return Err(Error::Cancelled);
Expand Down Expand Up @@ -2080,7 +2089,7 @@ impl<'gc> Loader<'gc> {
///
/// The current and total length are always reported as compressed lengths.
fn movie_loader_progress(
handle: Index,
handle: Handle,
uc: &mut UpdateContext<'_, 'gc>,
cur_len: usize,
total_len: usize,
Expand Down Expand Up @@ -2146,7 +2155,7 @@ impl<'gc> Loader<'gc> {

/// Report a movie loader completion to script code.
fn movie_loader_complete(
handle: Index,
handle: Handle,
uc: &mut UpdateContext<'_, 'gc>,
dobj: Option<DisplayObject<'gc>>,
status: u16,
Expand Down Expand Up @@ -2315,7 +2324,7 @@ impl<'gc> Loader<'gc> {
/// This is an associated function because we cannot borrow both the update
/// context and one of it's loaders.
fn movie_loader_error(
handle: Index,
handle: Handle,
uc: &mut UpdateContext<'_, 'gc>,
msg: AvmString<'gc>,
status: u16,
Expand Down
8 changes: 4 additions & 4 deletions core/src/local_connection.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ use crate::avm1::Object as Avm1Object;
use crate::avm2::object::LocalConnectionObject;
use crate::string::AvmString;
use gc_arena::Collect;
use generational_arena::{Arena, Index};
use slotmap::{DefaultKey, SlotMap};

pub type LocalConnectionHandle = Index;
pub type LocalConnectionHandle = DefaultKey;

#[derive(Collect)]
#[collect(no_drop)]
Expand Down Expand Up @@ -41,7 +41,7 @@ impl<'gc> LocalConnection<'gc> {

/// Manages the collection of local connections.
pub struct LocalConnections<'gc> {
connections: Arena<LocalConnection<'gc>>,
connections: SlotMap<LocalConnectionHandle, LocalConnection<'gc>>,
}

unsafe impl<'gc> Collect for LocalConnections<'gc> {
Expand All @@ -55,7 +55,7 @@ unsafe impl<'gc> Collect for LocalConnections<'gc> {
impl<'gc> LocalConnections<'gc> {
pub fn empty() -> Self {
Self {
connections: Arena::new(),
connections: SlotMap::new(),
}
}

Expand Down
8 changes: 4 additions & 4 deletions core/src/net_connection.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,12 @@ use crate::Player;
use flash_lso::packet::{Header, Message, Packet};
use flash_lso::types::{AMFVersion, Value as AmfValue};
use gc_arena::{Collect, DynamicRoot, Rootable};
use generational_arena::{Arena, Index};
use slotmap::{DefaultKey, SlotMap};
use std::fmt::{Debug, Formatter};
use std::rc::Rc;
use std::sync::{Mutex, Weak};

pub type NetConnectionHandle = Index;
pub type NetConnectionHandle = DefaultKey;

#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
pub enum ResponderCallback {
Expand Down Expand Up @@ -76,7 +76,7 @@ impl<'gc> From<Avm2NetConnectionObject<'gc>> for NetConnectionObject<'gc> {

/// Manages the collection of NetConnections.
pub struct NetConnections<'gc> {
connections: Arena<NetConnection<'gc>>,
connections: SlotMap<NetConnectionHandle, NetConnection<'gc>>,
}

unsafe impl<'gc> Collect for NetConnections<'gc> {
Expand All @@ -90,7 +90,7 @@ unsafe impl<'gc> Collect for NetConnections<'gc> {
impl<'gc> Default for NetConnections<'gc> {
fn default() -> Self {
Self {
connections: Arena::new(),
connections: SlotMap::new(),
}
}
}
Expand Down
Loading

0 comments on commit d59e925

Please sign in to comment.