refactor: use a RwLock for event listeners
This commit is contained in:
parent
36054ced03
commit
247612fad0
12
Cargo.lock
generated
12
Cargo.lock
generated
@ -1184,6 +1184,7 @@ dependencies = [
|
|||||||
"bevy_log",
|
"bevy_log",
|
||||||
"clap",
|
"clap",
|
||||||
"futures",
|
"futures",
|
||||||
|
"futures-locks",
|
||||||
"http-body-util",
|
"http-body-util",
|
||||||
"hyper",
|
"hyper",
|
||||||
"hyper-util",
|
"hyper-util",
|
||||||
@ -1317,6 +1318,17 @@ dependencies = [
|
|||||||
"pin-project-lite",
|
"pin-project-lite",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "futures-locks"
|
||||||
|
version = "0.7.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "45ec6fe3675af967e67c5536c0b9d44e34e6c52f86bedc4ea49c5317b8e94d06"
|
||||||
|
dependencies = [
|
||||||
|
"futures-channel",
|
||||||
|
"futures-task",
|
||||||
|
"tokio",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "futures-macro"
|
name = "futures-macro"
|
||||||
version = "0.3.31"
|
version = "0.3.31"
|
||||||
|
@ -21,6 +21,7 @@ bevy_app = "0"
|
|||||||
bevy_log = "0"
|
bevy_log = "0"
|
||||||
clap = { version = "4", features = ["derive"] }
|
clap = { version = "4", features = ["derive"] }
|
||||||
futures = "0"
|
futures = "0"
|
||||||
|
futures-locks = "0"
|
||||||
http-body-util = "0"
|
http-body-util = "0"
|
||||||
hyper = { version = "1", features = ["server"] }
|
hyper = { version = "1", features = ["server"] }
|
||||||
hyper-util = "0"
|
hyper-util = "0"
|
||||||
|
@ -123,7 +123,7 @@ pub async fn handle_event(client: Client, event: Event, state: State) -> anyhow:
|
|||||||
}
|
}
|
||||||
|
|
||||||
async fn call_listeners<T: Clone + IntoLuaMulti>(state: &State, event_type: &str, data: T) {
|
async fn call_listeners<T: Clone + IntoLuaMulti>(state: &State, event_type: &str, data: T) {
|
||||||
if let Some(listeners) = state.event_listeners.lock().await.get(event_type) {
|
if let Some(listeners) = state.event_listeners.read().await.get(event_type) {
|
||||||
for (_, listener) in listeners {
|
for (_, listener) in listeners {
|
||||||
if let Err(error) = listener.call_async::<()>(data.clone()).await {
|
if let Err(error) = listener.call_async::<()>(data.clone()).await {
|
||||||
error!("failed to call lua event listener for {event_type}: {error:?}");
|
error!("failed to call lua event listener for {event_type}: {error:?}");
|
||||||
|
@ -1,16 +1,9 @@
|
|||||||
use crate::ListenerMap;
|
use crate::ListenerMap;
|
||||||
use futures::{executor::block_on, lock::Mutex};
|
use futures::executor::block_on;
|
||||||
use mlua::{Function, Lua, Result, Table};
|
use mlua::{Function, Lua, Result, Table};
|
||||||
use std::{
|
use std::time::{SystemTime, UNIX_EPOCH};
|
||||||
sync::Arc,
|
|
||||||
time::{SystemTime, UNIX_EPOCH},
|
|
||||||
};
|
|
||||||
|
|
||||||
pub fn register_functions(
|
pub fn register_functions(lua: &Lua, globals: &Table, event_listeners: ListenerMap) -> Result<()> {
|
||||||
lua: &Lua,
|
|
||||||
globals: &Table,
|
|
||||||
event_listeners: Arc<Mutex<ListenerMap>>,
|
|
||||||
) -> Result<()> {
|
|
||||||
let m = event_listeners.clone();
|
let m = event_listeners.clone();
|
||||||
globals.set(
|
globals.set(
|
||||||
"add_listener",
|
"add_listener",
|
||||||
@ -18,7 +11,7 @@ pub fn register_functions(
|
|||||||
move |_, (event_type, callback, id): (String, Function, Option<String>)| {
|
move |_, (event_type, callback, id): (String, Function, Option<String>)| {
|
||||||
let m = m.clone();
|
let m = m.clone();
|
||||||
tokio::spawn(async move {
|
tokio::spawn(async move {
|
||||||
m.lock().await.entry(event_type).or_default().push((
|
m.write().await.entry(event_type).or_default().push((
|
||||||
id.unwrap_or(callback.info().name.unwrap_or(format!(
|
id.unwrap_or(callback.info().name.unwrap_or(format!(
|
||||||
"anonymous @ {}",
|
"anonymous @ {}",
|
||||||
SystemTime::now()
|
SystemTime::now()
|
||||||
@ -40,7 +33,7 @@ pub fn register_functions(
|
|||||||
lua.create_function(move |_, (event_type, target_id): (String, String)| {
|
lua.create_function(move |_, (event_type, target_id): (String, String)| {
|
||||||
let m = m.clone();
|
let m = m.clone();
|
||||||
tokio::spawn(async move {
|
tokio::spawn(async move {
|
||||||
let mut m = m.lock().await;
|
let mut m = m.write().await;
|
||||||
let empty = if let Some(listeners) = m.get_mut(&event_type) {
|
let empty = if let Some(listeners) = m.get_mut(&event_type) {
|
||||||
listeners.retain(|(id, _)| target_id != *id);
|
listeners.retain(|(id, _)| target_id != *id);
|
||||||
listeners.is_empty()
|
listeners.is_empty()
|
||||||
@ -58,7 +51,7 @@ pub fn register_functions(
|
|||||||
globals.set(
|
globals.set(
|
||||||
"get_listeners",
|
"get_listeners",
|
||||||
lua.create_function(move |lua, (): ()| {
|
lua.create_function(move |lua, (): ()| {
|
||||||
let m = block_on(event_listeners.lock());
|
let m = block_on(event_listeners.read());
|
||||||
|
|
||||||
let listeners = lua.create_table()?;
|
let listeners = lua.create_table()?;
|
||||||
for (event_type, callbacks) in m.iter() {
|
for (event_type, callbacks) in m.iter() {
|
||||||
|
@ -9,9 +9,8 @@ pub mod system;
|
|||||||
pub mod vec3;
|
pub mod vec3;
|
||||||
|
|
||||||
use crate::ListenerMap;
|
use crate::ListenerMap;
|
||||||
use futures::lock::Mutex;
|
|
||||||
use mlua::{Lua, Table};
|
use mlua::{Lua, Table};
|
||||||
use std::{io, sync::Arc, time::Duration};
|
use std::{io, time::Duration};
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
@ -27,7 +26,7 @@ pub enum Error {
|
|||||||
pub fn register_functions(
|
pub fn register_functions(
|
||||||
lua: &Lua,
|
lua: &Lua,
|
||||||
globals: &Table,
|
globals: &Table,
|
||||||
event_listeners: Arc<Mutex<ListenerMap>>,
|
event_listeners: ListenerMap,
|
||||||
) -> mlua::Result<()> {
|
) -> mlua::Result<()> {
|
||||||
globals.set(
|
globals.set(
|
||||||
"sleep",
|
"sleep",
|
||||||
|
@ -17,6 +17,7 @@ use bevy_log::{
|
|||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
use commands::{CommandSource, register};
|
use commands::{CommandSource, register};
|
||||||
use futures::lock::Mutex;
|
use futures::lock::Mutex;
|
||||||
|
use futures_locks::RwLock;
|
||||||
use mlua::{Function, Lua};
|
use mlua::{Function, Lua};
|
||||||
use std::{
|
use std::{
|
||||||
collections::HashMap,
|
collections::HashMap,
|
||||||
@ -29,12 +30,12 @@ use std::{
|
|||||||
|
|
||||||
const DEFAULT_SCRIPT_PATH: &str = "errornowatcher.lua";
|
const DEFAULT_SCRIPT_PATH: &str = "errornowatcher.lua";
|
||||||
|
|
||||||
type ListenerMap = HashMap<String, Vec<(String, Function)>>;
|
type ListenerMap = Arc<RwLock<HashMap<String, Vec<(String, Function)>>>>;
|
||||||
|
|
||||||
#[derive(Default, Clone, Component)]
|
#[derive(Default, Clone, Component)]
|
||||||
pub struct State {
|
pub struct State {
|
||||||
lua: Lua,
|
lua: Lua,
|
||||||
event_listeners: Arc<Mutex<ListenerMap>>,
|
event_listeners: ListenerMap,
|
||||||
commands: Arc<CommandDispatcher<Mutex<CommandSource>>>,
|
commands: Arc<CommandDispatcher<Mutex<CommandSource>>>,
|
||||||
http_address: Option<SocketAddr>,
|
http_address: Option<SocketAddr>,
|
||||||
}
|
}
|
||||||
@ -44,7 +45,7 @@ async fn main() -> anyhow::Result<()> {
|
|||||||
let args = arguments::Arguments::parse();
|
let args = arguments::Arguments::parse();
|
||||||
|
|
||||||
let script_path = args.script.unwrap_or(PathBuf::from(DEFAULT_SCRIPT_PATH));
|
let script_path = args.script.unwrap_or(PathBuf::from(DEFAULT_SCRIPT_PATH));
|
||||||
let event_listeners = Arc::new(Mutex::new(HashMap::new()));
|
let event_listeners = Arc::new(RwLock::new(HashMap::new()));
|
||||||
|
|
||||||
let lua = Lua::new();
|
let lua = Lua::new();
|
||||||
let globals = lua.globals();
|
let globals = lua.globals();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user