From ad753defdd48edb7ca396983f31ad739b467c7ce Mon Sep 17 00:00:00 2001 From: Ryo Yamashita Date: Tue, 8 Oct 2024 03:15:39 +0900 Subject: [PATCH] =?UTF-8?q?`drop=5Fbody`=E6=99=82=E3=81=AB`body`=E3=81=AE?= =?UTF-8?q?=E7=B5=82=E4=BA=86=E3=82=92=E5=BE=85=E3=81=A4=E3=82=88=E3=81=86?= =?UTF-8?q?=E3=81=AB=E3=81=99=E3=82=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Cargo.lock | 1 + Cargo.toml | 1 + crates/voicevox_core_c_api/Cargo.toml | 1 + crates/voicevox_core_c_api/src/c_impls.rs | 56 ++++++++++++++++------- 4 files changed, 43 insertions(+), 16 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index c32b36d5d..e501f78f8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4390,6 +4390,7 @@ dependencies = [ "libtest-mimic", "ndarray", "ndarray-stats", + "parking_lot", "predicates", "process_path", "ref-cast", diff --git a/Cargo.toml b/Cargo.toml index aaf8185ed..519562602 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -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" diff --git a/crates/voicevox_core_c_api/Cargo.toml b/crates/voicevox_core_c_api/Cargo.toml index 2852aaa69..3eca7ddb1 100644 --- a/crates/voicevox_core_c_api/Cargo.toml +++ b/crates/voicevox_core_c_api/Cargo.toml @@ -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"] } diff --git a/crates/voicevox_core_c_api/src/c_impls.rs b/crates/voicevox_core_c_api/src/c_impls.rs index 43497660b..b29a3f6ad 100644 --- a/crates/voicevox_core_c_api/src/c_impls.rs +++ b/crates/voicevox_core_c_api/src/c_impls.rs @@ -4,7 +4,7 @@ use std::{ ffi::CString, fmt::{Debug, Display}, mem, - ops::DerefMut, + ops::{Deref, DerefMut}, path::Path, sync::{Arc, LazyLock}, }; @@ -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::{ @@ -155,10 +156,15 @@ pub(crate) trait CApiObject: Default + Debug { fn heads() -> &'static boxcar::Vec; + #[expect(clippy::type_complexity, reason = "コメント書いてる")] fn bodies() -> &'static std::sync::Mutex< HashMap< usize, // `heads`の要素へのポインタのアドレス - Arc, + Arc< + parking_lot::RwLock< + Option, // `RwLock`をdropする直前まで`Some` + >, + >, >, >; @@ -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 } @@ -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::lock_bodies() + fn body(&self) -> impl Deref { + 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 { - fn lock_bodies() -> impl DerefMut>> { + fn lock_bodies( + ) -> impl DerefMut>>>> + { Self::bodies().lock().unwrap_or_else(|e| panic!("{e}")) } @@ -206,11 +228,6 @@ impl 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::() .split("::") @@ -235,9 +252,16 @@ impl CApiObject for H { &HEADS } - fn bodies() -> &'static std::sync::Mutex>> { - static BODIES: LazyLock>>> = - LazyLock::new(Default::default); + fn bodies() -> &'static std::sync::Mutex< + HashMap>>>, + > { + #[expect( + clippy::type_complexity, + reason = "`CApiObject::bodies`の方でコメント書いてる" + )] + static BODIES: LazyLock< + std::sync::Mutex>>>>, + > = LazyLock::new(Default::default); &BODIES } }