Implement targeted SocketBox Clone fix for shared mutable state
Co-authored-by: moe-charm <217100418+moe-charm@users.noreply.github.com>
This commit is contained in:
@ -56,18 +56,14 @@ pub struct SocketBox {
|
||||
|
||||
impl Clone for SocketBox {
|
||||
fn clone(&self) -> Self {
|
||||
// Read the current state values atomically
|
||||
let current_is_server = *self.is_server.lock().unwrap();
|
||||
let current_is_connected = *self.is_connected.lock().unwrap();
|
||||
|
||||
// For listener and stream, we can't clone them, so we'll share them
|
||||
// but create new Arc instances with the current state
|
||||
// 🔧 FIX: Share state containers for "Everything is Box" reference sharing
|
||||
// This ensures that clones of the same SocketBox share mutable state
|
||||
Self {
|
||||
base: BoxBase::new(), // New unique ID for clone
|
||||
base: BoxBase::new(), // New unique ID for clone (for debugging/identity)
|
||||
listener: Arc::clone(&self.listener), // Share the same listener
|
||||
stream: Arc::clone(&self.stream), // Share the same stream
|
||||
is_server: Arc::new(Mutex::new(current_is_server)), // New Arc with current value
|
||||
is_connected: Arc::new(Mutex::new(current_is_connected)), // New Arc with current value
|
||||
is_server: Arc::clone(&self.is_server), // 🔧 Share the same state container
|
||||
is_connected: Arc::clone(&self.is_connected), // 🔧 Share the same state container
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -51,7 +51,8 @@ impl NyashInterpreter {
|
||||
}
|
||||
|
||||
ASTNode::FieldAccess { object, field, .. } => {
|
||||
self.execute_field_access(object, field)
|
||||
let shared_result = self.execute_field_access(object, field)?;
|
||||
Ok((*shared_result).clone_box()) // Convert Arc to Box for external interface
|
||||
}
|
||||
|
||||
ASTNode::New { class, arguments, type_arguments, .. } => {
|
||||
@ -672,7 +673,7 @@ impl NyashInterpreter {
|
||||
|
||||
/// フィールドアクセスを実行 - Field access processing with weak reference support
|
||||
pub(super) fn execute_field_access(&mut self, object: &ASTNode, field: &str)
|
||||
-> Result<Box<dyn NyashBox>, RuntimeError> {
|
||||
-> Result<SharedNyashBox, RuntimeError> {
|
||||
|
||||
// 🔥 Static Boxアクセスチェック
|
||||
if let ASTNode::Variable { name, .. } = object {
|
||||
@ -734,8 +735,8 @@ impl NyashInterpreter {
|
||||
}
|
||||
}
|
||||
|
||||
// Normal field access - convert Arc back to Box for compatibility
|
||||
Ok((*field_value).clone_box())
|
||||
// Return the shared Arc reference directly
|
||||
Ok(field_value)
|
||||
} else {
|
||||
Err(RuntimeError::TypeError {
|
||||
message: format!("Cannot access field '{}' on non-instance type. Type: {}", field, obj_value.type_name()),
|
||||
|
||||
20
test_basic_sharing.nyash
Normal file
20
test_basic_sharing.nyash
Normal file
@ -0,0 +1,20 @@
|
||||
// Test basic field access sharing
|
||||
static box Main {
|
||||
init { mybox }
|
||||
|
||||
main() {
|
||||
me.mybox = new IntegerBox(100)
|
||||
|
||||
print("=== Test 1: Basic field access ===")
|
||||
local temp1
|
||||
temp1 = me.mybox
|
||||
print("temp1 ID: " + temp1.toString())
|
||||
|
||||
local temp2
|
||||
temp2 = me.mybox
|
||||
print("temp2 ID: " + temp2.toString())
|
||||
|
||||
// The IDs should be the same if sharing works
|
||||
return temp1
|
||||
}
|
||||
}
|
||||
21
test_box_id_sharing.nyash
Normal file
21
test_box_id_sharing.nyash
Normal file
@ -0,0 +1,21 @@
|
||||
// Test for Arc sharing - checking if same Box ID is returned
|
||||
static box Main {
|
||||
init { server }
|
||||
|
||||
main() {
|
||||
me.server = new SocketBox()
|
||||
|
||||
print("=== First access ===")
|
||||
local temp1
|
||||
temp1 = me.server
|
||||
print("Box ID: " + temp1.toString())
|
||||
|
||||
print("=== Second access ===")
|
||||
local temp2
|
||||
temp2 = me.server
|
||||
print("Box ID: " + temp2.toString())
|
||||
|
||||
// If Arc sharing works, both should have same ID
|
||||
return temp1
|
||||
}
|
||||
}
|
||||
24
test_simple_arc_fix.nyash
Normal file
24
test_simple_arc_fix.nyash
Normal file
@ -0,0 +1,24 @@
|
||||
// Simple test case to verify Arc sharing fix
|
||||
static box Main {
|
||||
init { counter }
|
||||
|
||||
main() {
|
||||
me.counter = new IntegerBox(42)
|
||||
|
||||
print("=== Initial value ===")
|
||||
print("counter: " + me.counter.to_string())
|
||||
|
||||
// Test if getting the same field returns the same object
|
||||
local temp1
|
||||
temp1 = me.counter
|
||||
|
||||
local temp2
|
||||
temp2 = me.counter
|
||||
|
||||
print("=== Testing shared reference ===")
|
||||
print("temp1: " + temp1.to_string())
|
||||
print("temp2: " + temp2.to_string())
|
||||
|
||||
return me.counter
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user