2025-08-09 15:14:44 +09:00
|
|
|
|
/*!
|
|
|
|
|
|
* Nyash Finalization System - Memory Management
|
2025-09-17 07:43:07 +09:00
|
|
|
|
*
|
2025-08-09 15:14:44 +09:00
|
|
|
|
* fini()によるメモリ管理システムの実装
|
|
|
|
|
|
* - 解放済みBoxの追跡
|
|
|
|
|
|
* - スコープベースの自動解放
|
|
|
|
|
|
* - 再代入時の自動解放
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
use crate::box_trait::NyashBox;
|
2025-08-20 00:21:20 +09:00
|
|
|
|
use crate::instance_v2::InstanceBox;
|
2025-08-09 15:14:44 +09:00
|
|
|
|
use lazy_static::lazy_static;
|
2025-09-17 07:43:07 +09:00
|
|
|
|
use std::collections::HashSet;
|
|
|
|
|
|
use std::fmt;
|
|
|
|
|
|
use std::sync::{Arc, Mutex};
|
2025-08-09 15:14:44 +09:00
|
|
|
|
|
|
|
|
|
|
lazy_static! {
|
|
|
|
|
|
/// グローバルな解放済みBox ID管理
|
|
|
|
|
|
static ref FINALIZED_BOXES: Arc<Mutex<HashSet<u64>>> = Arc::new(Mutex::new(HashSet::new()));
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// Boxが既に解放済みかチェック
|
|
|
|
|
|
pub fn is_finalized(box_id: u64) -> bool {
|
|
|
|
|
|
FINALIZED_BOXES.lock().unwrap().contains(&box_id)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// Boxを解放済みとして記録
|
|
|
|
|
|
pub fn mark_as_finalized(box_id: u64) {
|
|
|
|
|
|
FINALIZED_BOXES.lock().unwrap().insert(box_id);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// Box解放管理
|
|
|
|
|
|
pub struct BoxFinalizer {
|
|
|
|
|
|
/// このスコープで作成されたBox ID
|
|
|
|
|
|
created_boxes: Vec<(u64, Box<dyn NyashBox>)>,
|
|
|
|
|
|
/// finalization除外対象のBox ID(関数の返り値など)
|
|
|
|
|
|
excluded_boxes: HashSet<u64>,
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
impl BoxFinalizer {
|
|
|
|
|
|
pub fn new() -> Self {
|
|
|
|
|
|
Self {
|
|
|
|
|
|
created_boxes: Vec::new(),
|
|
|
|
|
|
excluded_boxes: HashSet::new(),
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-09-17 07:43:07 +09:00
|
|
|
|
|
2025-08-09 15:14:44 +09:00
|
|
|
|
/// 新しいBoxを追跡対象に追加
|
|
|
|
|
|
pub fn track(&mut self, nyash_box: Box<dyn NyashBox>) {
|
|
|
|
|
|
let box_id = nyash_box.box_id();
|
|
|
|
|
|
self.created_boxes.push((box_id, nyash_box));
|
|
|
|
|
|
}
|
2025-09-17 07:43:07 +09:00
|
|
|
|
|
2025-08-09 15:14:44 +09:00
|
|
|
|
/// 指定したBoxを解放対象から除外(関数の返り値など)
|
|
|
|
|
|
pub fn exclude_from_finalization(&mut self, nyash_box: &Box<dyn NyashBox>) {
|
|
|
|
|
|
let box_id = nyash_box.box_id();
|
|
|
|
|
|
self.excluded_boxes.insert(box_id);
|
|
|
|
|
|
}
|
2025-09-17 07:43:07 +09:00
|
|
|
|
|
2025-08-09 15:14:44 +09:00
|
|
|
|
/// スコープ終了時に全てのBoxを解放(除外対象を除く)
|
|
|
|
|
|
pub fn finalize_all(&mut self) {
|
|
|
|
|
|
// 作成順(古い順)に解放
|
|
|
|
|
|
for (box_id, nyash_box) in &self.created_boxes {
|
|
|
|
|
|
// 除外対象は解放しない
|
|
|
|
|
|
if self.excluded_boxes.contains(box_id) {
|
|
|
|
|
|
continue;
|
|
|
|
|
|
}
|
2025-09-17 07:43:07 +09:00
|
|
|
|
|
2025-08-09 15:14:44 +09:00
|
|
|
|
if !is_finalized(*box_id) {
|
|
|
|
|
|
// fini()メソッドを呼び出す(存在する場合)
|
2025-08-20 00:21:20 +09:00
|
|
|
|
if let Some(instance) = nyash_box.as_any().downcast_ref::<InstanceBox>() {
|
2025-08-09 15:14:44 +09:00
|
|
|
|
let _ = instance.fini();
|
|
|
|
|
|
}
|
|
|
|
|
|
mark_as_finalized(*box_id);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
self.created_boxes.clear();
|
|
|
|
|
|
self.excluded_boxes.clear();
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
impl Drop for BoxFinalizer {
|
|
|
|
|
|
fn drop(&mut self) {
|
|
|
|
|
|
self.finalize_all();
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
impl fmt::Debug for BoxFinalizer {
|
|
|
|
|
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
|
|
|
|
f.debug_struct("BoxFinalizer")
|
|
|
|
|
|
.field("created_boxes_count", &self.created_boxes.len())
|
|
|
|
|
|
.finish()
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#[cfg(test)]
|
|
|
|
|
|
mod tests {
|
|
|
|
|
|
use super::*;
|
2025-09-17 07:43:07 +09:00
|
|
|
|
|
2025-08-09 15:14:44 +09:00
|
|
|
|
#[test]
|
|
|
|
|
|
fn test_finalization_tracking() {
|
|
|
|
|
|
let box_id = 12345;
|
|
|
|
|
|
assert!(!is_finalized(box_id));
|
2025-09-17 07:43:07 +09:00
|
|
|
|
|
2025-08-09 15:14:44 +09:00
|
|
|
|
mark_as_finalized(box_id);
|
|
|
|
|
|
assert!(is_finalized(box_id));
|
2025-09-17 07:43:07 +09:00
|
|
|
|
|
2025-08-09 15:14:44 +09:00
|
|
|
|
// 二重解放チェック
|
|
|
|
|
|
mark_as_finalized(box_id); // 問題なし
|
|
|
|
|
|
assert!(is_finalized(box_id));
|
|
|
|
|
|
}
|
2025-09-17 07:43:07 +09:00
|
|
|
|
}
|