问题描述
不是我的喜好,但是我今天不得不写一些Rust,所以我试图创建一个只有一个端点的Rocket实例,但是在那个端点上,我需要访问在main期间创建的变量。该变量需要很长时间才能实例化,所以这就是我在此处执行该操作的原因。
我的问题是我找不到安全通过它的方法。无论我做什么,即使该库似乎是线程安全的,编译器仍会抱怨线程安全:https://github.com/brave/adblock-rust/pull/130(在我的本地实例上找到了承诺的代码)
|
18 | / lazy_static! {
19 | | static ref rules_engine: Mutex<Vec<Engine>> = Mutex::new(vec![]);
20 | | }
| |_^ `std::rc::Rc<std::cell::RefCell<lifeguard::CappedCollection<std::vec::Vec<u64>>>>` cannot be sent between threads safely
|
...这是我的代码:
#![feature(proc_macro_hygiene,decl_macro)]
#[macro_use]
extern crate rocket;
use std::fs::File;
use std::io::{self,BufRead};
use std::path::Path;
use lazy_static::lazy_static;
use std::sync::Mutex;
use adblock::engine::Engine;
use adblock::lists::FilterFormat;
use rocket::request::{Form,FormError,FormDataError};
lazy_static! {
static ref rules_engine: Mutex<Vec<Engine>> = Mutex::new(vec![]);
}
fn main() {
if !Path::new("./rules.txt").exists() {
println!("rules file does not exist")
} else {
println!("loading rules");
let mut rules = vec![];
if let Ok(lines) = read_lines("./rules.txt") {
for line in lines {
if let Ok(ip) = line {
rules.insert(0,ip)
}
}
let eng = Engine::from_rules(&rules,FilterFormat::Standard);
rules_engine.lock().unwrap().push(eng);
rocket().launch();
}
}
}
#[derive(Debug,FromForm)]
struct FormInput<> {
#[form(field = "textarea")]
text_area: String
}
#[post("/",data = "<sink>")]
fn sink(sink: Result<Form<FormInput>,FormError>) -> String {
match sink {
Ok(form) => {
format!("{:?}",&*form)
}
Err(FormDataError::Io(_)) => format!("Form input was invalid UTF-8."),Err(FormDataError::Malformed(f)) | Err(FormDataError::Parse(_,f)) => {
format!("Invalid form input: {}",f)
}
}
}
fn rocket() -> rocket::Rocket {
rocket::ignite().mount("/",routes![sink])
}
fn read_lines<P>(filename: P) -> io::Result<io::Lines<io::BufReader<File>>>
where P: AsRef<Path>,{
let file = File::open(filename)?;
Ok(io::BufReader::new(file).lines())
}
在eng
端点方法中可以使用sink
的任何方式?
解决方法
Rc
也不是线程安全的,即使在互斥锁后面也是如此。看起来Rc
中使用的eng.blocker.pool.pool
是lifeguard::Pool
。因此,Engine
不是线程安全的(至少默认情况下)。
幸运的是,看来adblock板条箱有一个feature,称为“对象池”,它启用了该特定功能。删除该功能将(希望)使其线程安全。