mirror of
https://github.com/storytold/vectorcraft.git
synced 2026-11-09 06:06:38 +00:00
Plug-ins: a command list read during an install is not cached under the new revision
registry::install now changes the revision while it holds the plug-in set's write lock, so a reader that sees the new revision and lists the plug-ins always finds the new one. command_specs also skips caching a list when the revision changed while it was listing. Before, a menu or shortcut lookup that ran during an install could keep the old command list until the next install or removal.
This commit is contained in:
@@ -324,6 +324,11 @@ pub fn command_specs() -> Vec<&'static CommandSpec> {
|
||||
}
|
||||
let specs: Vec<&'static CommandSpec> =
|
||||
registry::list().iter().flat_map(|p| p.manifest().commands.iter().map(|c| spec_of(p, c)).collect::<Vec<_>>()).collect();
|
||||
// When a plug-in was installed or removed during the listing, the list may not match
|
||||
// `revision`. It is returned without being cached, and the next call lists again.
|
||||
if registry::revision() != revision {
|
||||
return specs;
|
||||
}
|
||||
let mut l = LISTED.write().unwrap_or_else(|e| e.into_inner());
|
||||
if l.specs.len() != specs.len() || l.specs.iter().zip(&specs).any(|(a, b)| !std::ptr::eq(*a, *b)) {
|
||||
l.generation += 1;
|
||||
|
||||
@@ -45,11 +45,13 @@ pub fn approved(plugin: &Plugin) -> bool {
|
||||
!m.asks_permissions() || granted(&m.id).is_some_and(|g| g.covers(&m.permissions()))
|
||||
}
|
||||
|
||||
/// Installs `plugin`, replacing one with the same id.
|
||||
/// Installs `plugin`, replacing one with the same id. The revision changes while the set is locked,
|
||||
/// so a caller that reads the new [`revision`] and then [`list`]s always finds the plug-in.
|
||||
pub fn install(mut plugin: Plugin) -> Arc<Plugin> {
|
||||
let mut plugins = PLUGINS.write().unwrap_or_else(|e| e.into_inner());
|
||||
plugin.set_serial(REVISION.fetch_add(1, Ordering::Relaxed) + 1);
|
||||
let p = Arc::new(plugin);
|
||||
PLUGINS.write().unwrap_or_else(|e| e.into_inner()).insert(p.id().to_string(), p.clone());
|
||||
plugins.insert(p.id().to_string(), p.clone());
|
||||
p
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user