rust新手:子线程中无法修改结构体里属性,提示borrowed data escapes outside of method。该怎么调整?查了很多帖子都没找到类似的解决方式
功能:
代码逻辑:
主要是server结构体中记录每个子线程中生成的流量日志记录.(模仿server服务端采集连接端最近30分钟流量使用信息)
里面涉及到一个自定义的环形链表数据结构,可以初始化大小,达到指定大小后,循环覆盖更新环形链表节点的信息。
错误信息:
borrowed data escapes outside of method
requirement occurs because of a mutable reference to `Server<'_>`
mutable references are invariant over their type parameter
see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variancerustcClick for full compiler diagnostic
traffic.rs(134, 14): `self` is a reference that is only valid in the method body
traffic.rs(134, 14): has type `&mut Server<'1>`
borrowed data escapes outside of method
`self` escapes the method body hererustcClick for full compiler diagnostic
traffic.rs(134, 14): `self` is a reference that is only valid in the method body
traffic.rs(134, 14): let's call the lifetime of this reference `'2`
borrowed data escapes outside of method
argument requires that `'2` must outlive `'static`rustcClick for full compiler diagnostic
traffic.rs(134, 14): `self` is a reference that is only valid in the method body
traffic.rs(134, 14): let's call the lifetime of this reference `'2`
下面是具体的简化后的代码逻辑:
use std::{cell::RefCell, sync::{Arc, Mutex}, collections::HashMap};
use chrono::Local;
#[allow(dead_code)]
struct LogNode<'a, K,V>{
pub key:K,
pub up:V,
pub down:V,
pub next:Option<Arc<RefCell<LogNode<'a, K,V>>>>,
pub before:Option<std::sync::Weak<RefCell<LogNode<'a, K,V>>>>
}
struct LinkIterator<'a,K,V>{
current:Option<Arc<RefCell<LogNode<'a, K,V>>>>,
source:Option<Arc<RefCell<LogNode<'a, K,V>>>>
}
impl <'a, K, V> LinkIterator<'a, K, V> {
pub fn new(source:Option<Arc<RefCell<LogNode<'a, K,V>>>>) -> Self {
LinkIterator {
current: None,
source
}
}
}
impl <'a, K,V> Iterator for LinkIterator<'a, K,V>{
type Item=Arc<RefCell<LogNode<'a, K,V>>>;
fn next(&mut self) -> Option<Self::Item> {
if self.current.is_none() && self.source.is_some(){
self.current=self.source.clone();
}else{
if std::ptr::eq(self.source.as_ref().unwrap().as_ptr(),self.current.as_ref().unwrap().as_ptr()) {
return None;
}
}
let current=&self.current.as_ref().unwrap().clone();
self.current=current.borrow().next.clone();
Some(current.clone())
}
}
#[allow(dead_code)]
struct LinkedMapList<'a, K,V>{
size:u16,
capacity:u16,
head:Option<Arc<RefCell<LogNode<'a, K,V>>>>,
_private: ()
}
unsafe impl <'a, K,T> Send for LinkedMapList<'a, K,T> {}
unsafe impl <'a, K,T> Sync for LinkedMapList<'a, K,T> {}
impl<'a,K,V> LinkedMapList<'a, K,V>{
fn new(capacity:u16)->Self{
LinkedMapList{
size: 0,
capacity: capacity,
head: None,
_private:(),
}
}
fn push(&mut self,key:K,up:V,down:V){
if &self.size < &self.capacity {
let current: Arc<RefCell<LogNode<'_, K, V>>>=Arc::new(RefCell::new(LogNode{ key, up,down,next:None, before:None}));
let sp=Some(Arc::clone(¤t));
let wp=Some(Arc::downgrade(¤t));
if self.head.is_none(){
self.head=Some(Arc::clone(¤t));
current.borrow_mut().next=sp;
current.borrow_mut().before=wp;
}else{
let head_node=self.head.clone().unwrap();
let tail_node=head_node.borrow_mut().before.clone().unwrap().upgrade().unwrap();
current.borrow_mut().next=tail_node.borrow_mut().next.clone();
current.borrow_mut().before=head_node.borrow_mut().before.clone();
tail_node.borrow_mut().next=sp;
head_node.borrow_mut().before=wp;
}
self.size+=1;
}else{
let head_node: Arc<RefCell<LogNode<'_, K, V>>>=self.head.clone().unwrap();
//直接修改该节点的值
head_node.borrow_mut().key=key;
head_node.borrow_mut().up=up;
head_node.borrow_mut().down=down;
//头节点标记后移
self.head=head_node.borrow_mut().next.clone();
}
}
fn iterator(&self)->Option<LinkIterator<'a,K,V>>{
return Some(LinkIterator::new(self.head.clone()));
}
}
#[allow(dead_code)]
pub struct TrafficContext<'a>{
log_context:Option<LinkedMapList<'a, String,String>>
}
impl<'a> TrafficContext<'a>{
pub fn push_log(&mut self,time:String,up:String,down:String){
if self.log_context.is_none() {
self.log_context=Some(LinkedMapList::new(600 as u16));
}
self.log_context.as_mut().unwrap().push(time, up, down);
// self.log_context.and_then(|context|Some(context.push(time, up, down)));
}
}
impl <'a> std::fmt::Display for TrafficContext<'a>{
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result{
write!(f, "[")?;
let list: &LinkedMapList<'_, String, String>=self.log_context.as_ref().unwrap();
let mut iterator=list.iterator().unwrap();
loop{
let current=iterator.next().clone();
if current.is_some() {
let cc=current.unwrap();
write!(f,"( time: {}, up {}, down {} )",cc.borrow().key,cc.borrow().up,cc.borrow().down)?;
}else{
break;
}
}
write!(f, "]")
}
}
struct TrafficContextMap<'a>{
traffic_map:HashMap<String,TrafficContext<'a>>
}
struct Server<'a>{
server_status: Arc<std::sync::atomic::AtomicBool>,
traffic_context_map:Arc<Mutex<RefCell<TrafficContextMap<'a>>>>,
}
impl Server<'_> {
fn start(&mut self) -> Result<bool, String> {
let local_status = Arc::clone(&self.server_status);
let _thread = std::thread::spawn(move || {
println!("count thread startting...");
'outer: loop {
for _ in 0..10 {
if local_status.load(std::sync::atomic::Ordering::Relaxed) {
break 'outer;
}
}
let locker=self.traffic_context_map.as_ref().clone();
let mut data=locker.lock().unwrap().get_mut();
let history_data=data.traffic_map.get("00001").as_mut().unwrap();
history_data.push_log(Local::now().format("%Y-%m-%d %H:%M:%S").to_string(), "123".to_owned(),"456".to_owned());
}
});
log::info!("adapter up success");
Ok(self.server_status.load(std::sync::atomic::Ordering::Relaxed))
}
}
#[test]
fn test_server() {
}
#[test]
fn test_tcontext() {
let mut tcontext: TrafficContext<'_>=TrafficContext{ log_context: None};
tcontext.push_log("2021-08-09".to_owned(), "23".to_owned(), "34".to_owned());
tcontext.push_log("2021-08-10".to_owned(), "22".to_owned(), "39".to_owned());
tcontext.push_log("2021-08-11".to_owned(), "2".to_owned(), "3".to_owned());
tcontext.push_log("2021-08-12".to_owned(), "93".to_owned(), "84".to_owned());
tcontext.push_log("2021-08-13".to_owned(), "0".to_owned(), "0".to_owned());
print!("info >> {}",tcontext);
}
1
共 2 条评论, 1 页
评论区
写评论使用scopedthread,确实可以了
--
👇
yuyidegit:
TrafficContextMap<'a>
这个带非'static生命周期的东西不能放到其他线程执行,除非你用scopedthreadTrafficContextMap<'a>
这个带非'static生命周期的东西不能放到其他线程执行,除非你用scopedthread