perf: use async locks
This commit is contained in:
+34
-29
@@ -2,8 +2,8 @@ use std::{
|
||||
collections::HashMap,
|
||||
fs,
|
||||
io::Write,
|
||||
sync::{Arc, Mutex, mpsc},
|
||||
ops::{Deref, DerefMut},
|
||||
sync::Arc,
|
||||
};
|
||||
|
||||
use axum::{
|
||||
@@ -19,7 +19,10 @@ use futures::StreamExt as _;
|
||||
use rand::random_bool;
|
||||
use serde::{Deserialize, Serialize, de};
|
||||
use serde_json::json;
|
||||
use tokio::time::{Duration, sleep};
|
||||
use tokio::{
|
||||
sync::{Mutex, mpsc},
|
||||
time::{Duration, sleep},
|
||||
};
|
||||
|
||||
#[derive(Deserialize, Serialize, Debug, Ord, Eq, PartialEq, PartialOrd, Clone)]
|
||||
struct Entry {
|
||||
@@ -62,24 +65,23 @@ async fn main() {
|
||||
let loscores: Arc<Mutex<Vec<Entry>>> = read_file(PATH_LOSCORES);
|
||||
let pingscores: Arc<Mutex<HashMap<String, (u64, u32)>>> = read_file(PATH_PINGSCORES);
|
||||
|
||||
let (tx, rx) = mpsc::channel::<LeaderboardUpdate>();
|
||||
let (tx, rx) = mpsc::channel::<LeaderboardUpdate>(1024);
|
||||
|
||||
{
|
||||
let (hiscores, loscores, pingscores) =
|
||||
(hiscores.clone(), loscores.clone(), pingscores.clone());
|
||||
tokio::spawn(async move {
|
||||
handle_hiscores(rx, &hiscores, &loscores, &pingscores);
|
||||
handle_hiscores(rx, &hiscores, &loscores, &pingscores).await;
|
||||
});
|
||||
}
|
||||
|
||||
{
|
||||
let pingscores = pingscores.clone();
|
||||
tokio::spawn(async move {
|
||||
loop
|
||||
// write pingscores every 30s
|
||||
{
|
||||
loop {
|
||||
sleep(Duration::from_millis(30000)).await;
|
||||
let pingscores = pingscores.lock().unwrap();
|
||||
let pingscores = pingscores.lock().await;
|
||||
let file_contents: String = serde_json::to_string(&pingscores.clone()).unwrap();
|
||||
drop(pingscores);
|
||||
let mut file = fs::OpenOptions::new()
|
||||
@@ -119,8 +121,8 @@ async fn leaderboard() -> Html<&'static str> {
|
||||
Html(include_str!("../leaderboard.html"))
|
||||
}
|
||||
// receiver: 0 for hiscore, 1 for loscore, 2 for pingscore
|
||||
fn handle_hiscores(
|
||||
rx: mpsc::Receiver<LeaderboardUpdate>,
|
||||
async fn handle_hiscores(
|
||||
mut rx: mpsc::Receiver<LeaderboardUpdate>,
|
||||
hiscores: &Mutex<Vec<Entry>>,
|
||||
loscores: &Mutex<Vec<Entry>>,
|
||||
pingscores: &Mutex<HashMap<String, (u64, u32)>>,
|
||||
@@ -154,7 +156,7 @@ fn handle_hiscores(
|
||||
}
|
||||
|
||||
// Panic galore
|
||||
let mut hiscores_lock = hiscores.lock().unwrap();
|
||||
let mut hiscores_lock = hiscores.lock().await;
|
||||
hiscores_lock.sort();
|
||||
hiscores_lock.reverse();
|
||||
let file_contents: String = serde_json::to_string(&hiscores_lock.clone()).unwrap();
|
||||
@@ -168,24 +170,23 @@ fn handle_hiscores(
|
||||
drop(file);
|
||||
|
||||
loop {
|
||||
let LeaderboardUpdate { name, update } = rx.recv().expect("channel error");
|
||||
let LeaderboardUpdate { name, update } = rx.recv().await.expect("channel error");
|
||||
|
||||
match update {
|
||||
LeaderboardUpdateType::Reset { hiscore_pingscore } => {
|
||||
// Hiscore
|
||||
update_scoretable(
|
||||
"hiscore",
|
||||
hiscores.lock().unwrap(),
|
||||
hiscores.lock().await,
|
||||
&name,
|
||||
hiscore_pingscore,
|
||||
PATH_HISCORES,
|
||||
);
|
||||
|
||||
// Pingscore
|
||||
let mut pingscores = pingscores.lock().unwrap();
|
||||
if hiscore_pingscore > pingscores.get(&*name).unwrap_or(&(0, 0)).1
|
||||
let mut pingscores = pingscores.lock().await;
|
||||
// pb
|
||||
{
|
||||
if hiscore_pingscore > pingscores.get(&*name).unwrap_or(&(0, 0)).1 {
|
||||
pingscores.entry(name.to_string()).or_insert((0, 0)).1 = hiscore_pingscore;
|
||||
println!("{name} new PB: {hiscore_pingscore}");
|
||||
};
|
||||
@@ -196,7 +197,7 @@ fn handle_hiscores(
|
||||
LeaderboardUpdateType::Increment { loscore } => {
|
||||
update_scoretable(
|
||||
"loscore",
|
||||
loscores.lock().unwrap(),
|
||||
loscores.lock().await,
|
||||
&name,
|
||||
loscore,
|
||||
PATH_LOSCORES,
|
||||
@@ -229,9 +230,9 @@ async fn handle_socket(
|
||||
let mut value: u32 = 0;
|
||||
|
||||
let msg = {
|
||||
let hiscores = hiscores.lock().unwrap();
|
||||
let loscores = loscores.lock().unwrap();
|
||||
let pingscores = pingscores.lock().unwrap();
|
||||
let hiscores = hiscores.lock().await;
|
||||
let loscores = loscores.lock().await;
|
||||
let pingscores = pingscores.lock().await;
|
||||
json!({ "hiscores": &*hiscores, "loscores": &*loscores, "pingscores": &*pingscores})
|
||||
.to_string()
|
||||
};
|
||||
@@ -258,12 +259,14 @@ async fn handle_socket(
|
||||
Ok(Message::Text(_)) => {
|
||||
if random_bool(CHANCE) {
|
||||
// reset
|
||||
let _ = tx.send(LeaderboardUpdate {
|
||||
name: name.clone(),
|
||||
update: LeaderboardUpdateType::Reset {
|
||||
hiscore_pingscore: value,
|
||||
},
|
||||
});
|
||||
let _ = tx
|
||||
.send(LeaderboardUpdate {
|
||||
name: name.clone(),
|
||||
update: LeaderboardUpdateType::Reset {
|
||||
hiscore_pingscore: value,
|
||||
},
|
||||
})
|
||||
.await;
|
||||
resets += 1;
|
||||
value = 0
|
||||
}
|
||||
@@ -271,10 +274,12 @@ async fn handle_socket(
|
||||
else {
|
||||
value += 1;
|
||||
if prev == 0 {
|
||||
let _ = tx.send(LeaderboardUpdate {
|
||||
name: name.clone(),
|
||||
update: LeaderboardUpdateType::Increment { loscore: resets },
|
||||
});
|
||||
let _ = tx
|
||||
.send(LeaderboardUpdate {
|
||||
name: name.clone(),
|
||||
update: LeaderboardUpdateType::Increment { loscore: resets },
|
||||
})
|
||||
.await;
|
||||
resets = 0;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user