Skip to content

Commit

Permalink
drop_body時にbodyの終了を待つようにする
Browse files Browse the repository at this point in the history
  • Loading branch information
qryxip committed Oct 7, 2024
1 parent 3e6ddf1 commit ad753de
Show file tree
Hide file tree
Showing 4 changed files with 43 additions and 16 deletions.
1 change: 1 addition & 0 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 @@ -59,6 +59,7 @@ ndarray-stats = "0.5.1"
octocrab = { version = "0.19.0", default-features = false }
once_cell = "1.20.1"
ouroboros = "0.18.4"
parking_lot = "0.12.1"
parse-display = "0.8.2"
pollster = "0.3.0"
predicates = "3.1.2"
Expand Down
1 change: 1 addition & 0 deletions crates/voicevox_core_c_api/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ easy-ext.workspace = true
educe.workspace = true
itertools.workspace = true
libc.workspace = true
parking_lot = { workspace = true, features = ["arc_lock"] }
process_path.workspace = true
ref-cast.workspace = true
serde_json = { workspace = true, features = ["preserve_order"] }
Expand Down
56 changes: 40 additions & 16 deletions crates/voicevox_core_c_api/src/c_impls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use std::{
ffi::CString,
fmt::{Debug, Display},
mem,
ops::DerefMut,
ops::{Deref, DerefMut},
path::Path,
sync::{Arc, LazyLock},
};
Expand All @@ -13,6 +13,7 @@ use camino::Utf8Path;
use duplicate::duplicate_item;
use easy_ext::ext;
use ref_cast::ref_cast_custom;
use tracing::warn;
use voicevox_core::{InitializeOptions, Result, SpeakerMeta, VoiceModelId};

use crate::{
Expand Down Expand Up @@ -155,10 +156,15 @@ pub(crate) trait CApiObject: Default + Debug {

fn heads() -> &'static boxcar::Vec<Self>;

#[expect(clippy::type_complexity, reason = "コメント書いてる")]
fn bodies() -> &'static std::sync::Mutex<
HashMap<
usize, // `heads`の要素へのポインタのアドレス
Arc<Self::RustApiObject>,
Arc<
parking_lot::RwLock<
Option<Self::RustApiObject>, // `RwLock`をdropする直前まで`Some`
>,
>,
>,
>;

Expand All @@ -167,7 +173,8 @@ pub(crate) trait CApiObject: Default + Debug {

let i = Self::heads().push(Default::default());
let this = &Self::heads()[i];
Self::lock_bodies().insert(this as *const _ as _, body.into());
let body = parking_lot::RwLock::new(body.into()).into();
Self::lock_bodies().insert(this as *const _ as _, body);
this
}

Expand All @@ -181,23 +188,38 @@ pub(crate) trait CApiObject: Default + Debug {
let body = Self::lock_bodies()
.remove(&(self as *const _ as _))
.unwrap_or_else(|| self.panic_for_deleted());
drop(Arc::into_inner(body).unwrap_or_else(|| self.panic_for_in_use()));

drop(
body.try_write_arc()
.unwrap_or_else(|| {
warn!("{} is still in use. Waiting before closing", self.display());
body.write_arc()
})
.take()
.unwrap_or_else(|| self.panic_for_deleted()),
);
}

/// # Panics
///
/// `drop_body`を呼んでいるとパニックする。
fn body(&self) -> Arc<Self::RustApiObject> {
Self::lock_bodies()
fn body(&self) -> impl Deref<Target = Self::RustApiObject> {
let body = Self::lock_bodies()
.get(&(self as *const _ as _))
.unwrap_or_else(|| self.panic_for_deleted())
.clone()
.read_arc();
voicevox_core::__internal::interop::raii::try_map_guard(body, |body| {
body.as_ref().ok_or(())
})
.unwrap_or_else(|()| self.panic_for_deleted())
}
}

#[ext]
impl<T: CApiObject> T {
fn lock_bodies() -> impl DerefMut<Target = HashMap<usize, Arc<Self::RustApiObject>>> {
fn lock_bodies(
) -> impl DerefMut<Target = HashMap<usize, Arc<parking_lot::RwLock<Option<Self::RustApiObject>>>>>
{
Self::bodies().lock().unwrap_or_else(|e| panic!("{e}"))
}

Expand All @@ -206,11 +228,6 @@ impl<T: CApiObject> T {
panic!("{display}は既に破棄されています");
}

fn panic_for_in_use(&self) -> ! {
let display = self.display();
panic!("{display}が破棄されようとしましたが、これはまだ利用中です");
}

fn display(&self) -> impl Display + '_ {
let type_name = any::type_name::<Self>()
.split("::")
Expand All @@ -235,9 +252,16 @@ impl CApiObject for H {
&HEADS
}

fn bodies() -> &'static std::sync::Mutex<HashMap<usize, Arc<Self::RustApiObject>>> {
static BODIES: LazyLock<std::sync::Mutex<HashMap<usize, Arc<B>>>> =
LazyLock::new(Default::default);
fn bodies() -> &'static std::sync::Mutex<
HashMap<usize, Arc<parking_lot::RwLock<Option<Self::RustApiObject>>>>,
> {
#[expect(
clippy::type_complexity,
reason = "`CApiObject::bodies`の方でコメント書いてる"
)]
static BODIES: LazyLock<
std::sync::Mutex<HashMap<usize, Arc<parking_lot::RwLock<Option<B>>>>>,
> = LazyLock::new(Default::default);
&BODIES
}
}

0 comments on commit ad753de

Please sign in to comment.