Im trying to figure out the best way to share a hashmap across threads in an actix web server. So far i've been able to do it successfully using Mutex
and RwLock
. but i ideally would like something like Arc-Swap
which does seem to be more efficient than the above primitives. However , im unable to update the data wrapped under an ArcSwap
and im not sure why
heres my code
fn update_timestamps(data: Arc<ArcSwapAny<Arc<HashMap<String, String>>>>) -> () {
loop {
thread::sleep(Duration::from_secs(5));
println!("Updating time........");
let now: DateTime<Local> = Local::now();
let mut new_data = *data.load();
*data.swap(Arc::clone(new_data));
}
}
async fn get_latest_timestamp(
data: web::Data<Arc<ArcSwapAny<Arc<HashMap<String, String>>>>>,
) -> String {
let wrapped_data = data.load();
match wrapped_data.get("time_now") {
Some(i) => String::from(i),
None => String::from("None"),
}
}
#[actix_web::main]
async fn main() -> std::io::Result<()> {
let mut hash = HashMap::new();
hash.insert(String::from("time_now"), Local::now().to_rfc2822());
let data = Arc::new(ArcSwap::from_pointee(hash));
let hash_clone = Arc::clone(&data);
thread::spawn(move || update_timestamps(hash_clone));
HttpServer::new(move || {
App::new()
.data(data.clone())
.route("/", web::get().to(get_latest_timestamp))
})
.bind("127.0.0.1:8080")?
.run()
.await
}
Im getting an error in this line
*data.swap(Arc::clone(new_data));
mismatched types
expected reference `&Arc<HashMap<String, String>>`
found struct `Arc<HashMap<String, String>>`
but if i add the borrow - i get the below error
cannot move out of an `Arc`
move occurs because value has type `HashMap<String, String>`, which does not implement the `Copy` trait
so is there a way i can move the HashMap out of Arc
?
Or am i doing something else wrong?