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:
@ -751,14 +751,14 @@ impl VM {
|
|||||||
if let Some(array_box) = box_value.as_any().downcast_ref::<crate::boxes::array::ArrayBox>() {
|
if let Some(array_box) = box_value.as_any().downcast_ref::<crate::boxes::array::ArrayBox>() {
|
||||||
match method {
|
match method {
|
||||||
"length" | "len" => {
|
"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)));
|
return Ok(Box::new(IntegerBox::new(items.len() as i64)));
|
||||||
},
|
},
|
||||||
"get" => {
|
"get" => {
|
||||||
// get(index) - get element at index
|
// get(index) - get element at index
|
||||||
if let Some(index_box) = _args.get(0) {
|
if let Some(index_box) = _args.get(0) {
|
||||||
if let Some(index_int) = index_box.as_any().downcast_ref::<IntegerBox>() {
|
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;
|
let index = index_int.value as usize;
|
||||||
if index < items.len() {
|
if index < items.len() {
|
||||||
return Ok(items[index].clone_box());
|
return Ok(items[index].clone_box());
|
||||||
|
|||||||
@ -176,7 +176,7 @@ impl StringBox {
|
|||||||
/// Join array elements using this string as delimiter
|
/// Join array elements using this string as delimiter
|
||||||
pub fn join(&self, array_box: Box<dyn NyashBox>) -> Box<dyn NyashBox> {
|
pub fn join(&self, array_box: Box<dyn NyashBox>) -> Box<dyn NyashBox> {
|
||||||
if let Some(array) = array_box.as_any().downcast_ref::<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()
|
.iter()
|
||||||
.map(|element| element.to_string_box().value)
|
.map(|element| element.to_string_box().value)
|
||||||
.collect();
|
.collect();
|
||||||
|
|||||||
@ -299,8 +299,8 @@ impl NyashBox for ArrayBox {
|
|||||||
|
|
||||||
fn equals(&self, other: &dyn NyashBox) -> BoolBox {
|
fn equals(&self, other: &dyn NyashBox) -> BoolBox {
|
||||||
if let Some(other_array) = other.as_any().downcast_ref::<ArrayBox>() {
|
if let Some(other_array) = other.as_any().downcast_ref::<ArrayBox>() {
|
||||||
let self_items = self.items.lock().unwrap();
|
let self_items = self.items.read().unwrap();
|
||||||
let other_items = other_array.items.lock().unwrap();
|
let other_items = other_array.items.read().unwrap();
|
||||||
|
|
||||||
if self_items.len() != other_items.len() {
|
if self_items.len() != other_items.len() {
|
||||||
return BoolBox::new(false);
|
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()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -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()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -100,7 +100,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::RwLock;
|
||||||
use chrono::Local;
|
use chrono::Local;
|
||||||
use crate::box_trait::{BoxCore, BoxBase, next_box_id, NyashBox, StringBox, BoolBox, VoidBox};
|
use crate::box_trait::{BoxCore, BoxBase, next_box_id, NyashBox, StringBox, BoolBox, VoidBox};
|
||||||
use crate::interpreter::RuntimeError;
|
use crate::interpreter::RuntimeError;
|
||||||
@ -110,10 +110,10 @@ use std::any::Any;
|
|||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct DebugBox {
|
pub struct DebugBox {
|
||||||
base: BoxBase,
|
base: BoxBase,
|
||||||
tracking_enabled: Arc<Mutex<bool>>,
|
tracking_enabled: RwLock<bool>,
|
||||||
tracked_boxes: Arc<Mutex<HashMap<String, TrackedBoxInfo>>>,
|
tracked_boxes: RwLock<HashMap<String, TrackedBoxInfo>>,
|
||||||
breakpoints: Arc<Mutex<Vec<String>>>,
|
breakpoints: RwLock<Vec<String>>,
|
||||||
call_stack: Arc<Mutex<Vec<CallInfo>>>,
|
call_stack: RwLock<Vec<CallInfo>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
@ -135,34 +135,34 @@ impl DebugBox {
|
|||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
DebugBox {
|
DebugBox {
|
||||||
base: BoxBase::new(),
|
base: BoxBase::new(),
|
||||||
tracking_enabled: Arc::new(Mutex::new(false)),
|
tracking_enabled: RwLock::new(false),
|
||||||
tracked_boxes: Arc::new(Mutex::new(HashMap::new())),
|
tracked_boxes: RwLock::new(HashMap::new()),
|
||||||
breakpoints: Arc::new(Mutex::new(Vec::new())),
|
breakpoints: RwLock::new(Vec::new()),
|
||||||
call_stack: Arc::new(Mutex::new(Vec::new())),
|
call_stack: RwLock::new(Vec::new()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn start_tracking(&self) -> Result<Box<dyn NyashBox>, RuntimeError> {
|
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;
|
*enabled = true;
|
||||||
println!("[DEBUG] Tracking started");
|
println!("[DEBUG] Tracking started");
|
||||||
Ok(Box::new(VoidBox::new()))
|
Ok(Box::new(VoidBox::new()))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn stop_tracking(&self) -> Result<Box<dyn NyashBox>, RuntimeError> {
|
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;
|
*enabled = false;
|
||||||
println!("[DEBUG] Tracking stopped");
|
println!("[DEBUG] Tracking stopped");
|
||||||
Ok(Box::new(VoidBox::new()))
|
Ok(Box::new(VoidBox::new()))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn track_box(&self, box_value: &dyn NyashBox, name: &str) -> Result<Box<dyn NyashBox>, RuntimeError> {
|
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 {
|
if !*enabled {
|
||||||
return Ok(Box::new(VoidBox::new()));
|
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 {
|
let info = TrackedBoxInfo {
|
||||||
box_type: box_value.type_name().to_string(),
|
box_type: box_value.type_name().to_string(),
|
||||||
@ -298,7 +298,7 @@ impl DebugBox {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_tracking(&self) -> Result<Box<dyn NyashBox>, RuntimeError> {
|
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)))
|
Ok(Box::new(BoolBox::new(*enabled)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -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>() {
|
} else if let Some(string_box) = value.as_any().downcast_ref::<StringBox>() {
|
||||||
Value::String(string_box.value.clone())
|
Value::String(string_box.value.clone())
|
||||||
} else if let Some(array_box) = value.as_any().downcast_ref::<ArrayBox>() {
|
} 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()
|
let arr: Vec<Value> = items.iter()
|
||||||
.map(|item| nyash_box_to_json_value(item.clone_box()))
|
.map(|item| nyash_box_to_json_value(item.clone_box()))
|
||||||
.collect();
|
.collect();
|
||||||
Value::Array(arr)
|
Value::Array(arr)
|
||||||
} else if let Some(map_box) = value.as_any().downcast_ref::<MapBox>() {
|
} else if let Some(map_box) = value.as_any().downcast_ref::<MapBox>() {
|
||||||
let data = map_box.get_data();
|
let data = map_box.get_data();
|
||||||
let map = data.lock().unwrap();
|
let map = data.read().unwrap();
|
||||||
let mut obj = serde_json::Map::new();
|
let mut obj = serde_json::Map::new();
|
||||||
for (key, val) in map.iter() {
|
for (key, val) in map.iter() {
|
||||||
obj.insert(key.clone(), nyash_box_to_json_value(val.clone_box()));
|
obj.insert(key.clone(), nyash_box_to_json_value(val.clone_box()));
|
||||||
|
|||||||
@ -6,36 +6,35 @@ use crate::box_trait::{NyashBox, StringBox, BoolBox, IntegerBox, BoxCore, BoxBas
|
|||||||
use crate::boxes::buffer::BufferBox;
|
use crate::boxes::buffer::BufferBox;
|
||||||
use crate::boxes::array::ArrayBox;
|
use crate::boxes::array::ArrayBox;
|
||||||
use std::any::Any;
|
use std::any::Any;
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::RwLock;
|
||||||
use std::io::{Read, Write, Result};
|
use std::io::{Read, Write, Result};
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
pub struct NyashStreamBox {
|
pub struct NyashStreamBox {
|
||||||
buffer: Arc<Mutex<Vec<u8>>>,
|
buffer: RwLock<Vec<u8>>,
|
||||||
position: Arc<Mutex<usize>>,
|
position: RwLock<usize>,
|
||||||
base: BoxBase,
|
base: BoxBase,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl NyashStreamBox {
|
impl NyashStreamBox {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
NyashStreamBox {
|
NyashStreamBox {
|
||||||
buffer: Arc::new(Mutex::new(Vec::new())),
|
buffer: RwLock::new(Vec::new()),
|
||||||
position: Arc::new(Mutex::new(0)),
|
position: RwLock::new(0),
|
||||||
base: BoxBase::new(),
|
base: BoxBase::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn from_data(data: Vec<u8>) -> Self {
|
pub fn from_data(data: Vec<u8>) -> Self {
|
||||||
NyashStreamBox {
|
NyashStreamBox {
|
||||||
buffer: Arc::new(Mutex::new(data)),
|
buffer: RwLock::new(data),
|
||||||
position: Arc::new(Mutex::new(0)),
|
position: RwLock::new(0),
|
||||||
base: BoxBase::new(),
|
base: BoxBase::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn read(&self, buf: &mut [u8]) -> Result<usize> {
|
pub fn read(&self, buf: &mut [u8]) -> Result<usize> {
|
||||||
let buffer = self.buffer.lock().unwrap();
|
let buffer = self.buffer.read().unwrap();
|
||||||
let mut position = self.position.lock().unwrap();
|
let mut position = self.position.write().unwrap();
|
||||||
|
|
||||||
let available = buffer.len().saturating_sub(*position);
|
let available = buffer.len().saturating_sub(*position);
|
||||||
let to_read = buf.len().min(available);
|
let to_read = buf.len().min(available);
|
||||||
@ -50,21 +49,21 @@ impl NyashStreamBox {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn write(&self, buf: &[u8]) -> Result<()> {
|
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);
|
buffer.extend_from_slice(buf);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn len(&self) -> usize {
|
pub fn len(&self) -> usize {
|
||||||
self.buffer.lock().unwrap().len()
|
self.buffer.read().unwrap().len()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn position(&self) -> usize {
|
pub fn position(&self) -> usize {
|
||||||
*self.position.lock().unwrap()
|
*self.position.read().unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn reset(&self) {
|
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();
|
let array_data = buffer_box.readAll();
|
||||||
// ArrayBoxをバイト配列に変換
|
// ArrayBoxをバイト配列に変換
|
||||||
if let Some(array_box) = array_data.as_any().downcast_ref::<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();
|
let mut bytes = Vec::new();
|
||||||
for item in items.iter() {
|
for item in items.iter() {
|
||||||
if let Some(int_box) = item.as_any().downcast_ref::<IntegerBox>() {
|
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 {
|
fn to_string_box(&self) -> StringBox {
|
||||||
let buffer = self.buffer.lock().unwrap();
|
let buffer = self.buffer.read().unwrap();
|
||||||
let position = self.position.lock().unwrap();
|
let position = self.position.read().unwrap();
|
||||||
StringBox::new(format!("NyashStreamBox({} bytes, pos: {})", buffer.len(), *position))
|
StringBox::new(format!("NyashStreamBox({} bytes, pos: {})", buffer.len(), *position))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -155,10 +154,10 @@ impl NyashBox for NyashStreamBox {
|
|||||||
|
|
||||||
fn equals(&self, other: &dyn NyashBox) -> BoolBox {
|
fn equals(&self, other: &dyn NyashBox) -> BoolBox {
|
||||||
if let Some(other_stream) = other.as_any().downcast_ref::<NyashStreamBox>() {
|
if let Some(other_stream) = other.as_any().downcast_ref::<NyashStreamBox>() {
|
||||||
let self_buffer = self.buffer.lock().unwrap();
|
let self_buffer = self.buffer.read().unwrap();
|
||||||
let self_position = self.position.lock().unwrap();
|
let self_position = self.position.read().unwrap();
|
||||||
let other_buffer = other_stream.buffer.lock().unwrap();
|
let other_buffer = other_stream.buffer.read().unwrap();
|
||||||
let other_position = other_stream.position.lock().unwrap();
|
let other_position = other_stream.position.read().unwrap();
|
||||||
BoolBox::new(*self_buffer == *other_buffer && *self_position == *other_position)
|
BoolBox::new(*self_buffer == *other_buffer && *self_position == *other_position)
|
||||||
} else {
|
} else {
|
||||||
BoolBox::new(false)
|
BoolBox::new(false)
|
||||||
@ -176,8 +175,8 @@ impl BoxCore for NyashStreamBox {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn fmt_box(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn fmt_box(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
let buffer = self.buffer.lock().unwrap();
|
let buffer = self.buffer.read().unwrap();
|
||||||
let position = self.position.lock().unwrap();
|
let position = self.position.read().unwrap();
|
||||||
write!(f, "NyashStreamBox({} bytes, pos: {})", buffer.len(), *position)
|
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 {
|
impl std::fmt::Display for NyashStreamBox {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
self.fmt_box(f)
|
self.fmt_box(f)
|
||||||
|
|||||||
@ -117,7 +117,7 @@ impl StringBox {
|
|||||||
pub fn join(&self, array_box: Box<dyn NyashBox>) -> Box<dyn NyashBox> {
|
pub fn join(&self, array_box: Box<dyn NyashBox>) -> Box<dyn NyashBox> {
|
||||||
use crate::boxes::array::ArrayBox;
|
use crate::boxes::array::ArrayBox;
|
||||||
if let Some(array) = array_box.as_any().downcast_ref::<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()
|
.iter()
|
||||||
.map(|element| element.to_string_box().value)
|
.map(|element| element.to_string_box().value)
|
||||||
.collect();
|
.collect();
|
||||||
|
|||||||
Reference in New Issue
Block a user