Improve panic safety and queue performance

This commit is contained in:
Filip Tibell 2024-02-06 15:19:54 +01:00
parent 5eddd99422
commit 63ecbf7b61
No known key found for this signature in database
2 changed files with 38 additions and 16 deletions

View file

@ -46,6 +46,7 @@ impl ThreadQueue {
Ok(id)
}
#[inline]
pub fn drain_items<'outer, 'lua>(
&'outer self,
lua: &'lua Lua,
@ -56,11 +57,17 @@ impl ThreadQueue {
self.queue.try_iter().map(|stored| stored.into_inner(lua))
}
#[inline]
pub async fn wait_for_item(&self) {
if self.queue.is_empty() {
self.event.listen().await;
}
}
#[inline]
pub fn is_empty(&self) -> bool {
self.queue.is_empty()
}
}
/**

View file

@ -5,6 +5,7 @@ use std::{
process::ExitCode,
rc::{Rc, Weak as WeakRc},
sync::{Arc, Weak as WeakArc},
thread::panicking,
};
use futures_lite::prelude::*;
@ -417,7 +418,10 @@ impl<'lua> Runtime<'lua> {
// Empty executor = we didn't spawn any new Lua tasks
// above, and there are no remaining tasks to run later
if local_exec.is_empty() {
if local_exec.is_empty()
&& self.queue_spawn.is_empty()
&& self.queue_defer.is_empty()
{
break;
}
}
@ -445,20 +449,31 @@ impl<'lua> Runtime<'lua> {
impl Drop for Runtime<'_> {
fn drop(&mut self) {
self.lua
.remove_app_data::<SpawnedThreadQueue>()
.expect(ERR_METADATA_REMOVED);
self.lua
.remove_app_data::<DeferredThreadQueue>()
.expect(ERR_METADATA_REMOVED);
self.lua
.remove_app_data::<ThreadErrorCallback>()
.expect(ERR_METADATA_REMOVED);
self.lua
.remove_app_data::<ThreadResultMap>()
.expect(ERR_METADATA_REMOVED);
self.lua
.remove_app_data::<Exit>()
.expect(ERR_METADATA_REMOVED);
if panicking() {
// Do not cause further panics if already panicking, as
// this may abort the program instead of safely unwinding
self.lua.remove_app_data::<SpawnedThreadQueue>();
self.lua.remove_app_data::<DeferredThreadQueue>();
self.lua.remove_app_data::<ThreadErrorCallback>();
self.lua.remove_app_data::<ThreadResultMap>();
self.lua.remove_app_data::<Exit>();
} else {
// In any other case we panic if metadata was removed incorrectly
self.lua
.remove_app_data::<SpawnedThreadQueue>()
.expect(ERR_METADATA_REMOVED);
self.lua
.remove_app_data::<DeferredThreadQueue>()
.expect(ERR_METADATA_REMOVED);
self.lua
.remove_app_data::<ThreadErrorCallback>()
.expect(ERR_METADATA_REMOVED);
self.lua
.remove_app_data::<ThreadResultMap>()
.expect(ERR_METADATA_REMOVED);
self.lua
.remove_app_data::<Exit>()
.expect(ERR_METADATA_REMOVED);
}
}
}