rust - 具有分离的外部和内部可变性的全局静态Vec

标签 rust thread-safety

我有一个代表状态的全局静态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_recvffi_send

我在想我必须在Vec外部有一个RwLock,以便能够在ffi_connect期间锁定(我不在乎当时是否阻塞),但在ffi_recvffi_send期间会获得多个不可变的引用。然后,我需要以某种方式获取Vec指向的对象的内部可变性。

我不想在同一对象上同时ffi_recvffi_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/

相关文章:

rust - 如何使用泛型数组?

rust - 返回 Option 时有些不需要?

rust - 如何找到 Linux 主目录的路径?

C++ Boost read_json 崩溃,我有#define BOOST_SPIRIT_THREADSAFE

java - BoneCP:getConnection 方法是线程安全的还是我们必须处理它?

即使文件存在,Rust 也找不到模块

c# - 我可以从 System.Net.Security.SslStream 获得什么级别的线程安全?

embedded - 嵌入式系统中线程安全的单消费者、单生产者 FIFO

c# - 围绕多个语句的锁定语句是否确保所有更改对其他线程可见(前提是它们进入相同的互斥体)?

binding - let-rebinding 和标准赋值有什么区别?