Skip to content

Commit f4f0bfb

Browse files
authored
fix: Optimize use of hash tables in platform adapters (#485)
1 parent 0a51225 commit f4f0bfb

File tree

7 files changed

+40
-36
lines changed

7 files changed

+40
-36
lines changed

Cargo.lock

Lines changed: 2 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

platforms/macos/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ default-target = "x86_64-apple-darwin"
1717
[dependencies]
1818
accesskit = { version = "0.17.0", path = "../../common" }
1919
accesskit_consumer = { version = "0.25.0", path = "../../consumer" }
20-
once_cell = "1.13.0"
20+
hashbrown = { version = "0.15", default-features = false, features = ["default-hasher"] }
2121
objc2 = "0.5.1"
2222
objc2-foundation = { version = "0.2.0", features = [
2323
"NSArray",

platforms/macos/src/context.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,11 @@
55

66
use accesskit::{ActionHandler, ActionRequest, NodeId};
77
use accesskit_consumer::Tree;
8+
use hashbrown::HashMap;
89
use objc2::rc::{Id, WeakId};
910
use objc2_app_kit::*;
1011
use objc2_foundation::MainThreadMarker;
11-
use std::{cell::RefCell, collections::HashMap, rc::Rc};
12+
use std::{cell::RefCell, rc::Rc};
1213

1314
use crate::node::PlatformNode;
1415

platforms/macos/src/event.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,11 @@
55

66
use accesskit::{Live, NodeId, Role};
77
use accesskit_consumer::{FilterResult, Node, TreeChangeHandler};
8+
use hashbrown::HashSet;
89
use objc2::runtime::{AnyObject, ProtocolObject};
910
use objc2_app_kit::*;
1011
use objc2_foundation::{NSMutableDictionary, NSNumber, NSString};
11-
use std::{collections::HashSet, rc::Rc};
12+
use std::rc::Rc;
1213

1314
use crate::{context::Context, filters::filter, node::NodeWrapper};
1415

platforms/macos/src/subclass.rs

Lines changed: 30 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,11 @@ use objc2::{
1919
};
2020
use objc2_app_kit::{NSView, NSWindow};
2121
use objc2_foundation::{NSArray, NSObject, NSPoint};
22-
use once_cell::sync::Lazy;
23-
use std::{cell::RefCell, collections::HashMap, ffi::c_void, sync::Mutex};
22+
use std::{cell::RefCell, ffi::c_void, sync::Mutex};
2423

2524
use crate::{event::QueuedEvents, Adapter};
2625

27-
static SUBCLASSES: Lazy<Mutex<HashMap<&'static AnyClass, &'static AnyClass>>> =
28-
Lazy::new(|| Mutex::new(HashMap::new()));
26+
static SUBCLASSES: Mutex<Vec<(&'static AnyClass, &'static AnyClass)>> = Mutex::new(Vec::new());
2927

3028
static ASSOCIATED_OBJECT_KEY: u8 = 0;
3129

@@ -163,34 +161,38 @@ impl SubclassingAdapter {
163161
)
164162
};
165163
let mut subclasses = SUBCLASSES.lock().unwrap();
166-
let entry = subclasses.entry(prev_class);
167-
let subclass = entry.or_insert_with(|| {
168-
let name = format!("AccessKitSubclassOf{}", prev_class.name());
169-
let mut builder = ClassBuilder::new(&name, prev_class).unwrap();
170-
unsafe {
171-
builder.add_method(
172-
sel!(superclass),
173-
superclass as unsafe extern "C" fn(_, _) -> _,
174-
);
175-
builder.add_method(
176-
sel!(accessibilityChildren),
177-
children as unsafe extern "C" fn(_, _) -> _,
178-
);
179-
builder.add_method(
180-
sel!(accessibilityFocusedUIElement),
181-
focus as unsafe extern "C" fn(_, _) -> _,
182-
);
183-
builder.add_method(
184-
sel!(accessibilityHitTest:),
185-
hit_test as unsafe extern "C" fn(_, _, _) -> _,
186-
);
164+
let subclass = match subclasses.iter().find(|entry| entry.0 == prev_class) {
165+
Some(entry) => entry.1,
166+
None => {
167+
let name = format!("AccessKitSubclassOf{}", prev_class.name());
168+
let mut builder = ClassBuilder::new(&name, prev_class).unwrap();
169+
unsafe {
170+
builder.add_method(
171+
sel!(superclass),
172+
superclass as unsafe extern "C" fn(_, _) -> _,
173+
);
174+
builder.add_method(
175+
sel!(accessibilityChildren),
176+
children as unsafe extern "C" fn(_, _) -> _,
177+
);
178+
builder.add_method(
179+
sel!(accessibilityFocusedUIElement),
180+
focus as unsafe extern "C" fn(_, _) -> _,
181+
);
182+
builder.add_method(
183+
sel!(accessibilityHitTest:),
184+
hit_test as unsafe extern "C" fn(_, _, _) -> _,
185+
);
186+
}
187+
let class = builder.register();
188+
subclasses.push((prev_class, class));
189+
class
187190
}
188-
builder.register()
189-
});
191+
};
190192
// SAFETY: Changing the view's class is only safe because
191193
// the subclass doesn't add any instance variables;
192194
// it uses an associated object instead.
193-
unsafe { object_setClass(view as *mut _, (*subclass as *const AnyClass).cast()) };
195+
unsafe { object_setClass(view as *mut _, (subclass as *const AnyClass).cast()) };
194196
Self {
195197
view: retained_view,
196198
associated,

platforms/windows/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ targets = []
1818
[dependencies]
1919
accesskit = { version = "0.17.0", path = "../../common" }
2020
accesskit_consumer = { version = "0.25.0", path = "../../consumer" }
21+
hashbrown = { version = "0.15", default-features = false, features = ["default-hasher"] }
2122
paste = "1.0"
2223
static_assertions = "1.1.0"
2324
windows-core = "0.58.0"

platforms/windows/src/adapter.rs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,8 @@ use accesskit::{
88
TreeUpdate,
99
};
1010
use accesskit_consumer::{FilterResult, Node, Tree, TreeChangeHandler};
11-
use std::{
12-
collections::HashSet,
13-
sync::{atomic::Ordering, Arc},
14-
};
11+
use hashbrown::HashSet;
12+
use std::sync::{atomic::Ordering, Arc};
1513
use windows::Win32::{
1614
Foundation::*,
1715
UI::{Accessibility::*, WindowsAndMessaging::*},

0 commit comments

Comments
 (0)