简体   繁体   English

具有拆分外部和内部可变性的全局 static Vec

[英]Global static Vec with split exterior and interior mutability

I have a global static Vec that represents a state.我有一个代表 state 的全局 static Vec。 It seems to be no other solution than a global state (I am developing a library that can be used by a threaded program to make network connections and I don't want the program to manage any of the internal data - such as currently open sockets).除了全局 state 之外,似乎没有其他解决方案(我正在开发一个可由线程程序用于建立网络连接的库,我不希望该程序管理任何内部数据 - 例如当前打开的套接字)。

Example of what I have in mind (does not compile):我想到的例子(不编译):

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)
}

The question is how should I implement SOCKETS in order to be able to call ffi_recv and ffi_send from two threads?问题是我应该如何实现SOCKETS以便能够从两个线程调用ffi_recvffi_send

I'm thinking that I have to have a RwLock outside the Vec, in order to be able to lock during ffi_connect (I don't care about blocking at that point) but get multiple immutable references during ffi_recv and ffi_send .我在想我必须在 Vec 之外有一个RwLock ,以便能够在ffi_connect期间锁定(我不关心此时的阻塞),但在ffi_recvffi_send期间获得多个不可变引用。 Then, somehow I need to get the interior mutability of the object that the Vec is pointing to.然后,不知何故,我需要获得 Vec 指向的 object 的内部可变性。

I DON'T want to be able to ffi_recv and ffi_send at the same time on the same object (this MUST throw an error)我不想在同一个 object 上同时ffi_recvffi_send (这必须抛出一个错误)

I almost had the answer inside my question...我几乎在我的问题中得到了答案......

I just had to RwLock<Vec<RwLock<Connection>>> .我只需要RwLock<Vec<RwLock<Connection>>> In order to mutate the Vec itself, the outer write lock would be locked.为了改变 Vec 本身,外部写锁将被锁定。 In order to mutate an item of the Vec, the outer lock would be read blocked where RwLock allows multiple locks.为了改变 Vec 的一个项目,外部锁将被读阻塞,而 RwLock 允许多个锁。 Then the inner RwLock could be either read or write locked.然后内部 RwLock 可以被读取或写入锁定。

ffi_connect becomes: 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);
}

And ffi_recv becomes: 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)
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM