我有一个代表状态的全局静态Vec。似乎除了全局状态外没有其他解决方案(我正在开发一个可由线程程序用来建立网络连接的库,并且我不希望该程序管理任何内部数据-例如当前打开的套接字)。
我想到的示例(无法编译):
lazy_static! {
static ref SOCKETS: Vec<Connection> = Vec::new();
}
#[no_mangle]
pub extern fn ffi_connect(address: *const u8, length: usize) {
let address_str = unsafe { from_raw_parts(address, length) };
let conn = internal_connect(address_str);
// Now I need to lock all the Vec to mutate it
SOCKETS.push(conn);
}
#[no_mangle]
pub extern fn ffi_recv(index: usize, msg: *mut c_void, size: usize) -> usize {
let buf = unsafe { from_raw_parts(msg as *const u8, size) };
// Now I need to lock ONLY the specific "index" item to mutate it
let conn = SOCKETS.get_mut(index);
conn.read(buf)
}
#[no_mangle]
pub extern fn ffi_send(index: usize, msg: *mut c_void, size: usize) -> usize {
let buf = unsafe { from_raw_parts(msg as *const u8, size) };
// Now I need to lock ONLY the specific "index" item to mutate it
let conn = SOCKETS.get_mut(index);
conn.write(buf)
}
问题是我应该如何实现
SOCKETS
以便能够从两个线程调用ffi_recv
和ffi_send
?我在想我必须在Vec外部有一个
RwLock
,以便能够在ffi_connect
期间锁定(我不在乎当时是否阻塞),但在ffi_recv
和ffi_send
期间会获得多个不可变的引用。然后,我需要以某种方式获取Vec指向的对象的内部可变性。我不想在同一对象上同时
ffi_recv
和ffi_send
(这必须抛出错误)
最佳答案
我的问题里几乎有答案...
我只需要RwLock<Vec<RwLock<Connection>>>
。为了使Vec本身发生变异,外部写锁将被锁定。为了使Vec的项发生变异,RwLock允许多个锁时,外部锁将被读取为阻塞状态。然后,内部RwLock可以被读或写锁定。ffi_connect
变为:
#[no_mangle]
pub extern fn ffi_connect(address: *const u8, length: usize) {
let address_str = unsafe { from_raw_parts(address, length) };
let conn = internal_connect(address_str);
let mut socket_lock = SOCKETS.write().unwrap();
// Nobody can read or write SOCKETS right now
socket_lock.push(conn);
}
ffi_recv
变为:#[no_mangle]
pub extern fn ffi_recv(index: usize, msg: *mut c_void, size: usize) -> usize {
let buf = unsafe { from_raw_parts(msg as *const u8, size) };
// Now I need to lock ONLY the specific "index" item to mutate it
let socket_lock = SOCKETS.read().unwrap();
// SOCKETS can only be "read" locked right now
let mut conn = socket_lock.get(index).write().unwrap();
// Nobody else can read or write to this exact object
// SOCKETS remains readable though!
conn.read(buf)
}
关于rust - 具有分离的外部和内部可变性的全局静态Vec,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62352297/