实现 "move" 线程语义
Implementing "move" thread semantics
我想写一个这样调用的函数:
send("message","address");
其他线程在做什么
let k = recv("address");
println!("{}",k);
看到 message
。
特别是消息可能很大,因此我希望使用 "move" 或 "zero-copy" 语义来发送消息。
在 C 中,解决方案类似于:
- 在堆上分配消息
- 有一个全局的、线程安全的 hashmap 映射 "address" 到某个内存位置
- 在发送时将指针写入内存位置,并使用信号量唤醒接收方
- 接收时从内存位置读取指针,并等待信号量处理新消息
但根据另一个 SO 问题,第 2 步“”。所以我希望看到一种更符合 Rust 习惯的方法来解决这个问题。
你会自动获得这些移动语义,并通过将大值放入 Box
(即在堆上分配它们)来实现轻量级移动。使用 type ConcurrentHashMap<K, V> = Mutex<HashMap<K, V>>;
作为线程安全哈希映射(有多种方法可以改进),可能有:
use std::collections::{HashMap, RingBuf};
use std::sync::Mutex;
type ConcurrentHashMap<K, V> = Mutex<HashMap<K, V>>;
lazy_static! {
pub static ref MAP: ConcurrentHashMap<String, RingBuf<String>> = {
Mutex::new(HashMap::new())
}
}
fn send(message: String, address: String) {
MAP.lock()
// find the place this message goes
.entry(address)
.get()
// create a new RingBuf if this address was empty
.unwrap_or_else(|v| v.insert(RingBuf::new()))
// add the message on the back
.push_back(message)
}
fn recv(address: &str) -> Option<String> {
MAP.lock()
.get_mut(address)
// pull the message off the front
.and_then(|buf| buf.pop_front())
}
该代码使用 lazy_static!
宏来实现全局哈希图(最好使用包装 Arc<ConcurrentHashMap<...>
的本地对象,fwiw,因为全局状态可以对程序进行推理行为严厉)。它还使用 RingBuf
作为队列,以便消息为给定的 address
存储起来。如果您一次只希望支持一条消息,类型可以是 ConcurrentHashMap<String, String>
,send
可以变成 MAP.lock().insert(address, message)
而 recv
只是 MAP.lock().remove(address)
.
(注意。我没有编译这个,所以类型可能不完全匹配。)
我想写一个这样调用的函数:
send("message","address");
其他线程在做什么
let k = recv("address");
println!("{}",k);
看到 message
。
特别是消息可能很大,因此我希望使用 "move" 或 "zero-copy" 语义来发送消息。
在 C 中,解决方案类似于:
- 在堆上分配消息
- 有一个全局的、线程安全的 hashmap 映射 "address" 到某个内存位置
- 在发送时将指针写入内存位置,并使用信号量唤醒接收方
- 接收时从内存位置读取指针,并等待信号量处理新消息
但根据另一个 SO 问题,第 2 步“
你会自动获得这些移动语义,并通过将大值放入 Box
(即在堆上分配它们)来实现轻量级移动。使用 type ConcurrentHashMap<K, V> = Mutex<HashMap<K, V>>;
作为线程安全哈希映射(有多种方法可以改进),可能有:
use std::collections::{HashMap, RingBuf};
use std::sync::Mutex;
type ConcurrentHashMap<K, V> = Mutex<HashMap<K, V>>;
lazy_static! {
pub static ref MAP: ConcurrentHashMap<String, RingBuf<String>> = {
Mutex::new(HashMap::new())
}
}
fn send(message: String, address: String) {
MAP.lock()
// find the place this message goes
.entry(address)
.get()
// create a new RingBuf if this address was empty
.unwrap_or_else(|v| v.insert(RingBuf::new()))
// add the message on the back
.push_back(message)
}
fn recv(address: &str) -> Option<String> {
MAP.lock()
.get_mut(address)
// pull the message off the front
.and_then(|buf| buf.pop_front())
}
该代码使用 lazy_static!
宏来实现全局哈希图(最好使用包装 Arc<ConcurrentHashMap<...>
的本地对象,fwiw,因为全局状态可以对程序进行推理行为严厉)。它还使用 RingBuf
作为队列,以便消息为给定的 address
存储起来。如果您一次只希望支持一条消息,类型可以是 ConcurrentHashMap<String, String>
,send
可以变成 MAP.lock().insert(address, message)
而 recv
只是 MAP.lock().remove(address)
.
(注意。我没有编译这个,所以类型可能不完全匹配。)