Phase 9.75-B: Convert StreamBox from Arc<Mutex> to RwLock, progress on DebugBox

Co-authored-by: moe-charm <217100418+moe-charm@users.noreply.github.com>
This commit is contained in:
copilot-swe-agent[bot]
2025-08-14 23:59:11 +00:00
parent ffa09b17fb
commit 5bcaa14b52
8 changed files with 92 additions and 45 deletions

View File

@ -751,14 +751,14 @@ impl VM {
if let Some(array_box) = box_value.as_any().downcast_ref::<crate::boxes::array::ArrayBox>() {
match method {
"length" | "len" => {
let items = array_box.items.lock().unwrap();
let items = array_box.items.read().unwrap();
return Ok(Box::new(IntegerBox::new(items.len() as i64)));
},
"get" => {
// get(index) - get element at index
if let Some(index_box) = _args.get(0) {
if let Some(index_int) = index_box.as_any().downcast_ref::<IntegerBox>() {
let items = array_box.items.lock().unwrap();
let items = array_box.items.read().unwrap();
let index = index_int.value as usize;
if index < items.len() {
return Ok(items[index].clone_box());

View File

@ -176,7 +176,7 @@ impl StringBox {
/// Join array elements using this string as delimiter
pub fn join(&self, array_box: Box<dyn NyashBox>) -> Box<dyn NyashBox> {
if let Some(array) = array_box.as_any().downcast_ref::<ArrayBox>() {
let strings: Vec<String> = array.items.lock().unwrap()
let strings: Vec<String> = array.items.read().unwrap()
.iter()
.map(|element| element.to_string_box().value)
.collect();

View File

@ -299,8 +299,8 @@ impl NyashBox for ArrayBox {
fn equals(&self, other: &dyn NyashBox) -> BoolBox {
if let Some(other_array) = other.as_any().downcast_ref::<ArrayBox>() {
let self_items = self.items.lock().unwrap();
let other_items = other_array.items.lock().unwrap();
let self_items = self.items.read().unwrap();
let other_items = other_array.items.read().unwrap();
if self_items.len() != other_items.len() {
return BoolBox::new(false);
@ -318,3 +318,14 @@ impl NyashBox for ArrayBox {
}
}
}
// Debug implementation for ArrayBox
impl std::fmt::Debug for ArrayBox {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let items = self.items.read().unwrap();
f.debug_struct("ArrayBox")
.field("id", &self.base.id)
.field("length", &items.len())
.finish()
}
}

View File

@ -216,3 +216,14 @@ impl NyashBox for BufferBox {
}
}
}
// Debug implementation for BufferBox
impl std::fmt::Debug for BufferBox {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let data = self.data.read().unwrap();
f.debug_struct("BufferBox")
.field("id", &self.base.id)
.field("length", &data.len())
.finish()
}
}

View File

@ -100,7 +100,7 @@
*/
use std::collections::HashMap;
use std::sync::{Arc, Mutex};
use std::sync::RwLock;
use chrono::Local;
use crate::box_trait::{BoxCore, BoxBase, next_box_id, NyashBox, StringBox, BoolBox, VoidBox};
use crate::interpreter::RuntimeError;
@ -110,10 +110,10 @@ use std::any::Any;
#[derive(Debug, Clone)]
pub struct DebugBox {
base: BoxBase,
tracking_enabled: Arc<Mutex<bool>>,
tracked_boxes: Arc<Mutex<HashMap<String, TrackedBoxInfo>>>,
breakpoints: Arc<Mutex<Vec<String>>>,
call_stack: Arc<Mutex<Vec<CallInfo>>>,
tracking_enabled: RwLock<bool>,
tracked_boxes: RwLock<HashMap<String, TrackedBoxInfo>>,
breakpoints: RwLock<Vec<String>>,
call_stack: RwLock<Vec<CallInfo>>,
}
#[derive(Debug, Clone)]
@ -135,34 +135,34 @@ impl DebugBox {
pub fn new() -> Self {
DebugBox {
base: BoxBase::new(),
tracking_enabled: Arc::new(Mutex::new(false)),
tracked_boxes: Arc::new(Mutex::new(HashMap::new())),
breakpoints: Arc::new(Mutex::new(Vec::new())),
call_stack: Arc::new(Mutex::new(Vec::new())),
tracking_enabled: RwLock::new(false),
tracked_boxes: RwLock::new(HashMap::new()),
breakpoints: RwLock::new(Vec::new()),
call_stack: RwLock::new(Vec::new()),
}
}
pub fn start_tracking(&self) -> Result<Box<dyn NyashBox>, RuntimeError> {
let mut enabled = self.tracking_enabled.lock().unwrap();
let mut enabled = self.tracking_enabled.write().unwrap();
*enabled = true;
println!("[DEBUG] Tracking started");
Ok(Box::new(VoidBox::new()))
}
pub fn stop_tracking(&self) -> Result<Box<dyn NyashBox>, RuntimeError> {
let mut enabled = self.tracking_enabled.lock().unwrap();
let mut enabled = self.tracking_enabled.write().unwrap();
*enabled = false;
println!("[DEBUG] Tracking stopped");
Ok(Box::new(VoidBox::new()))
}
pub fn track_box(&self, box_value: &dyn NyashBox, name: &str) -> Result<Box<dyn NyashBox>, RuntimeError> {
let enabled = self.tracking_enabled.lock().unwrap();
let enabled = self.tracking_enabled.read().unwrap();
if !*enabled {
return Ok(Box::new(VoidBox::new()));
}
let mut tracked = self.tracked_boxes.lock().unwrap();
let mut tracked = self.tracked_boxes.write().unwrap();
let info = TrackedBoxInfo {
box_type: box_value.type_name().to_string(),
@ -298,7 +298,7 @@ impl DebugBox {
}
pub fn is_tracking(&self) -> Result<Box<dyn NyashBox>, RuntimeError> {
let enabled = self.tracking_enabled.lock().unwrap();
let enabled = self.tracking_enabled.read().unwrap();
Ok(Box::new(BoolBox::new(*enabled)))
}

View File

@ -242,14 +242,14 @@ fn nyash_box_to_json_value(value: Box<dyn NyashBox>) -> Value {
} else if let Some(string_box) = value.as_any().downcast_ref::<StringBox>() {
Value::String(string_box.value.clone())
} else if let Some(array_box) = value.as_any().downcast_ref::<ArrayBox>() {
let items = array_box.items.lock().unwrap();
let items = array_box.items.read().unwrap();
let arr: Vec<Value> = items.iter()
.map(|item| nyash_box_to_json_value(item.clone_box()))
.collect();
Value::Array(arr)
} else if let Some(map_box) = value.as_any().downcast_ref::<MapBox>() {
let data = map_box.get_data();
let map = data.lock().unwrap();
let map = data.read().unwrap();
let mut obj = serde_json::Map::new();
for (key, val) in map.iter() {
obj.insert(key.clone(), nyash_box_to_json_value(val.clone_box()));

View File

@ -6,36 +6,35 @@ use crate::box_trait::{NyashBox, StringBox, BoolBox, IntegerBox, BoxCore, BoxBas
use crate::boxes::buffer::BufferBox;
use crate::boxes::array::ArrayBox;
use std::any::Any;
use std::sync::{Arc, Mutex};
use std::sync::RwLock;
use std::io::{Read, Write, Result};
#[derive(Debug, Clone)]
pub struct NyashStreamBox {
buffer: Arc<Mutex<Vec<u8>>>,
position: Arc<Mutex<usize>>,
buffer: RwLock<Vec<u8>>,
position: RwLock<usize>,
base: BoxBase,
}
impl NyashStreamBox {
pub fn new() -> Self {
NyashStreamBox {
buffer: Arc::new(Mutex::new(Vec::new())),
position: Arc::new(Mutex::new(0)),
buffer: RwLock::new(Vec::new()),
position: RwLock::new(0),
base: BoxBase::new(),
}
}
pub fn from_data(data: Vec<u8>) -> Self {
NyashStreamBox {
buffer: Arc::new(Mutex::new(data)),
position: Arc::new(Mutex::new(0)),
buffer: RwLock::new(data),
position: RwLock::new(0),
base: BoxBase::new(),
}
}
pub fn read(&self, buf: &mut [u8]) -> Result<usize> {
let buffer = self.buffer.lock().unwrap();
let mut position = self.position.lock().unwrap();
let buffer = self.buffer.read().unwrap();
let mut position = self.position.write().unwrap();
let available = buffer.len().saturating_sub(*position);
let to_read = buf.len().min(available);
@ -50,21 +49,21 @@ impl NyashStreamBox {
}
pub fn write(&self, buf: &[u8]) -> Result<()> {
let mut buffer = self.buffer.lock().unwrap();
let mut buffer = self.buffer.write().unwrap();
buffer.extend_from_slice(buf);
Ok(())
}
pub fn len(&self) -> usize {
self.buffer.lock().unwrap().len()
self.buffer.read().unwrap().len()
}
pub fn position(&self) -> usize {
*self.position.lock().unwrap()
*self.position.read().unwrap()
}
pub fn reset(&self) {
*self.position.lock().unwrap() = 0;
*self.position.write().unwrap() = 0;
}
/// ストリームに書き込み
@ -75,7 +74,7 @@ impl NyashStreamBox {
let array_data = buffer_box.readAll();
// ArrayBoxをバイト配列に変換
if let Some(array_box) = array_data.as_any().downcast_ref::<ArrayBox>() {
let items = array_box.items.lock().unwrap();
let items = array_box.items.read().unwrap();
let mut bytes = Vec::new();
for item in items.iter() {
if let Some(int_box) = item.as_any().downcast_ref::<IntegerBox>() {
@ -142,8 +141,8 @@ impl NyashBox for NyashStreamBox {
}
fn to_string_box(&self) -> StringBox {
let buffer = self.buffer.lock().unwrap();
let position = self.position.lock().unwrap();
let buffer = self.buffer.read().unwrap();
let position = self.position.read().unwrap();
StringBox::new(format!("NyashStreamBox({} bytes, pos: {})", buffer.len(), *position))
}
@ -155,10 +154,10 @@ impl NyashBox for NyashStreamBox {
fn equals(&self, other: &dyn NyashBox) -> BoolBox {
if let Some(other_stream) = other.as_any().downcast_ref::<NyashStreamBox>() {
let self_buffer = self.buffer.lock().unwrap();
let self_position = self.position.lock().unwrap();
let other_buffer = other_stream.buffer.lock().unwrap();
let other_position = other_stream.position.lock().unwrap();
let self_buffer = self.buffer.read().unwrap();
let self_position = self.position.read().unwrap();
let other_buffer = other_stream.buffer.read().unwrap();
let other_position = other_stream.position.read().unwrap();
BoolBox::new(*self_buffer == *other_buffer && *self_position == *other_position)
} else {
BoolBox::new(false)
@ -176,8 +175,8 @@ impl BoxCore for NyashStreamBox {
}
fn fmt_box(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let buffer = self.buffer.lock().unwrap();
let position = self.position.lock().unwrap();
let buffer = self.buffer.read().unwrap();
let position = self.position.read().unwrap();
write!(f, "NyashStreamBox({} bytes, pos: {})", buffer.len(), *position)
}
@ -190,6 +189,32 @@ impl BoxCore for NyashStreamBox {
}
}
// Clone implementation for NyashStreamBox (needed since RwLock doesn't auto-derive Clone)
impl Clone for NyashStreamBox {
fn clone(&self) -> Self {
let buffer = self.buffer.read().unwrap();
let position = self.position.read().unwrap();
NyashStreamBox {
buffer: RwLock::new(buffer.clone()),
position: RwLock::new(*position),
base: BoxBase::new(),
}
}
}
// Debug implementation for NyashStreamBox
impl std::fmt::Debug for NyashStreamBox {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let buffer = self.buffer.read().unwrap();
let position = self.position.read().unwrap();
f.debug_struct("NyashStreamBox")
.field("id", &self.base.id)
.field("buffer_len", &buffer.len())
.field("position", &position)
.finish()
}
}
impl std::fmt::Display for NyashStreamBox {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
self.fmt_box(f)

View File

@ -117,7 +117,7 @@ impl StringBox {
pub fn join(&self, array_box: Box<dyn NyashBox>) -> Box<dyn NyashBox> {
use crate::boxes::array::ArrayBox;
if let Some(array) = array_box.as_any().downcast_ref::<ArrayBox>() {
let strings: Vec<String> = array.items.lock().unwrap()
let strings: Vec<String> = array.items.read().unwrap()
.iter()
.map(|element| element.to_string_box().value)
.collect();