Detailed changes
@@ -5001,11 +5001,13 @@ checksum = "bd0c93bb4b0c6d9b77f4435b0ae98c24d17f1c45b2ff844c6151a07256ca923b"
[[package]]
name = "dispatch2"
-version = "0.3.0"
+version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "89a09f22a6c6069a18470eb92d2298acf25463f14256d24778e1230d789a2aec"
+checksum = "1e0e367e4e7da84520dedcac1901e4da967309406d1e51017ae1abfb97adbd38"
dependencies = [
"bitflags 2.10.0",
+ "block2",
+ "libc",
"objc2",
]
@@ -7677,7 +7679,6 @@ version = "0.1.0"
dependencies = [
"anyhow",
"async-task",
- "bindgen 0.71.1",
"block",
"cbindgen",
"cocoa 0.26.0",
@@ -7689,6 +7690,7 @@ dependencies = [
"core-video",
"ctor",
"derive_more 0.99.20",
+ "dispatch2",
"etagere",
"foreign-types 0.5.0",
"futures 0.3.31",
@@ -34,6 +34,7 @@ core-text = "21"
core-video.workspace = true
ctor.workspace = true
derive_more.workspace = true
+dispatch2 = "0.3.1"
etagere = "0.2"
# WARNING: If you change this, you must also publish a new version of zed-font-kit to crates.io
font-kit = { git = "https://github.com/zed-industries/font-kit", rev = "110523127440aefb11ce0cf280ae7c5071337ec5", package = "zed-font-kit", version = "0.14.1-zed", optional = true }
@@ -57,6 +58,5 @@ util.workspace = true
uuid.workspace = true
[target.'cfg(target_os = "macos")'.build-dependencies]
-bindgen = "0.71"
cbindgen = { version = "0.28.0", default-features = false }
-gpui.workspace = true
+gpui.workspace = true
@@ -15,8 +15,6 @@ mod macos_build {
use cbindgen::Config;
pub fn run() {
- generate_dispatch_bindings();
-
let header_path = generate_shader_bindings();
#[cfg(feature = "runtime_shaders")]
@@ -25,39 +23,6 @@ mod macos_build {
compile_metal_shaders(&header_path);
}
- fn generate_dispatch_bindings() {
- println!("cargo:rustc-link-lib=framework=System");
-
- let bindings = bindgen::Builder::default()
- .header("src/dispatch.h")
- .allowlist_var("_dispatch_main_q")
- .allowlist_var("_dispatch_source_type_data_add")
- .allowlist_var("DISPATCH_QUEUE_PRIORITY_HIGH")
- .allowlist_var("DISPATCH_QUEUE_PRIORITY_DEFAULT")
- .allowlist_var("DISPATCH_QUEUE_PRIORITY_LOW")
- .allowlist_var("DISPATCH_TIME_NOW")
- .allowlist_function("dispatch_get_global_queue")
- .allowlist_function("dispatch_async_f")
- .allowlist_function("dispatch_after_f")
- .allowlist_function("dispatch_time")
- .allowlist_function("dispatch_source_merge_data")
- .allowlist_function("dispatch_source_create")
- .allowlist_function("dispatch_source_set_event_handler_f")
- .allowlist_function("dispatch_resume")
- .allowlist_function("dispatch_suspend")
- .allowlist_function("dispatch_source_cancel")
- .allowlist_function("dispatch_set_context")
- .parse_callbacks(Box::new(bindgen::CargoCallbacks::new()))
- .layout_tests(false)
- .generate()
- .expect("unable to generate bindings");
-
- let out_path = PathBuf::from(env::var("OUT_DIR").unwrap());
- bindings
- .write_to_file(out_path.join("dispatch_sys.rs"))
- .expect("couldn't write dispatch bindings");
- }
-
fn generate_shader_bindings() -> PathBuf {
let output_path = PathBuf::from(env::var("OUT_DIR").unwrap()).join("scene.h");
@@ -1,2 +0,0 @@
-#include <dispatch/dispatch.h>
-#include <dispatch/source.h>
@@ -1,7 +1,4 @@
-#![allow(non_upper_case_globals)]
-#![allow(non_camel_case_types)]
-#![allow(non_snake_case)]
-
+use dispatch2::{DispatchQueue, DispatchQueueGlobalPriority, DispatchTime, GlobalQueueIdentifier};
use gpui::{
GLOBAL_THREAD_TIMINGS, PlatformDispatcher, Priority, RunnableMeta, RunnableVariant,
THREAD_TIMINGS, TaskTiming, ThreadTaskTimings,
@@ -26,21 +23,10 @@ use objc::{
};
use std::{
ffi::c_void,
- ptr::{NonNull, addr_of},
+ ptr::NonNull,
time::{Duration, Instant},
};
-/// All items in the generated file are marked as pub, so we're gonna wrap it in a separate mod to prevent
-/// these pub items from leaking into public API.
-pub(crate) mod dispatch_sys {
- include!(concat!(env!("OUT_DIR"), "/dispatch_sys.rs"));
-}
-
-use dispatch_sys::*;
-pub(crate) fn dispatch_get_main_queue() -> dispatch_queue_t {
- addr_of!(_dispatch_main_q) as *const _ as dispatch_queue_t
-}
-
pub(crate) struct MacDispatcher;
impl MacDispatcher {
@@ -89,43 +75,32 @@ impl PlatformDispatcher for MacDispatcher {
Priority::RealtimeAudio => {
panic!("RealtimeAudio priority should use spawn_realtime, not dispatch")
}
- Priority::High => DISPATCH_QUEUE_PRIORITY_HIGH as isize,
- Priority::Medium => DISPATCH_QUEUE_PRIORITY_DEFAULT as isize,
- Priority::Low => DISPATCH_QUEUE_PRIORITY_LOW as isize,
+ Priority::High => DispatchQueueGlobalPriority::High,
+ Priority::Medium => DispatchQueueGlobalPriority::Default,
+ Priority::Low => DispatchQueueGlobalPriority::Low,
};
unsafe {
- dispatch_async_f(
- dispatch_get_global_queue(queue_priority, 0),
- context,
- Some(trampoline as unsafe extern "C" fn(*mut c_void)),
- );
+ DispatchQueue::global_queue(GlobalQueueIdentifier::Priority(queue_priority))
+ .exec_async_f(context, trampoline);
}
}
fn dispatch_on_main_thread(&self, runnable: RunnableVariant, _priority: Priority) {
let context = runnable.into_raw().as_ptr() as *mut c_void;
unsafe {
- dispatch_async_f(
- dispatch_get_main_queue(),
- context,
- Some(trampoline as unsafe extern "C" fn(*mut c_void)),
- );
+ DispatchQueue::main().exec_async_f(context, trampoline);
}
}
fn dispatch_after(&self, duration: Duration, runnable: RunnableVariant) {
let context = runnable.into_raw().as_ptr() as *mut c_void;
+ let queue = DispatchQueue::global_queue(GlobalQueueIdentifier::Priority(
+ DispatchQueueGlobalPriority::High,
+ ));
+ let when = DispatchTime::NOW.time(duration.as_nanos() as i64);
unsafe {
- let queue =
- dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH.try_into().unwrap(), 0);
- let when = dispatch_time(DISPATCH_TIME_NOW as u64, duration.as_nanos() as i64);
- dispatch_after_f(
- when,
- queue,
- context,
- Some(trampoline as unsafe extern "C" fn(*mut c_void)),
- );
+ DispatchQueue::exec_after_f(when, &queue, context, trampoline);
}
}
@@ -1,26 +1,21 @@
-use crate::{
- dispatch_get_main_queue,
- dispatcher::dispatch_sys::{
- _dispatch_source_type_data_add, dispatch_resume, dispatch_set_context,
- dispatch_source_cancel, dispatch_source_create, dispatch_source_merge_data,
- dispatch_source_set_event_handler_f, dispatch_source_t, dispatch_suspend,
- },
-};
use anyhow::Result;
use core_graphics::display::CGDirectDisplayID;
+use dispatch2::{
+ _dispatch_source_type_data_add, DispatchObject, DispatchQueue, DispatchRetained, DispatchSource,
+};
use std::ffi::c_void;
use util::ResultExt;
pub struct DisplayLink {
display_link: Option<sys::DisplayLink>,
- frame_requests: dispatch_source_t,
+ frame_requests: DispatchRetained<DispatchSource>,
}
impl DisplayLink {
pub fn new(
display_id: CGDirectDisplayID,
data: *mut c_void,
- callback: unsafe extern "C" fn(*mut c_void),
+ callback: extern "C" fn(*mut c_void),
) -> Result<DisplayLink> {
unsafe extern "C" fn display_link_callback(
_display_link_out: *mut sys::CVDisplayLink,
@@ -31,31 +26,26 @@ impl DisplayLink {
frame_requests: *mut c_void,
) -> i32 {
unsafe {
- let frame_requests = frame_requests as dispatch_source_t;
- dispatch_source_merge_data(frame_requests, 1);
+ let frame_requests = &*(frame_requests as *const DispatchSource);
+ frame_requests.merge_data(1);
0
}
}
unsafe {
- let frame_requests = dispatch_source_create(
- &_dispatch_source_type_data_add,
+ let frame_requests = DispatchSource::new(
+ &raw const _dispatch_source_type_data_add as *mut _,
0,
0,
- dispatch_get_main_queue(),
- );
- dispatch_set_context(
- crate::dispatch_sys::dispatch_object_t {
- _ds: frame_requests,
- },
- data,
+ Some(DispatchQueue::main()),
);
- dispatch_source_set_event_handler_f(frame_requests, Some(callback));
+ frame_requests.set_context(data);
+ frame_requests.set_event_handler_f(callback);
let display_link = sys::DisplayLink::new(
display_id,
display_link_callback,
- frame_requests as *mut c_void,
+ &*frame_requests as *const DispatchSource as *mut c_void,
)?;
Ok(Self {
@@ -67,9 +57,7 @@ impl DisplayLink {
pub fn start(&mut self) -> Result<()> {
unsafe {
- dispatch_resume(crate::dispatch_sys::dispatch_object_t {
- _ds: self.frame_requests,
- });
+ self.frame_requests.resume();
self.display_link.as_mut().unwrap().start()?;
}
Ok(())
@@ -77,9 +65,7 @@ impl DisplayLink {
pub fn stop(&mut self) -> Result<()> {
unsafe {
- dispatch_suspend(crate::dispatch_sys::dispatch_object_t {
- _ds: self.frame_requests,
- });
+ self.frame_requests.suspend();
self.display_link.as_mut().unwrap().stop()?;
}
Ok(())
@@ -97,9 +83,9 @@ impl Drop for DisplayLink {
//
// We might also want to upgrade to CADisplayLink, but that requires dropping old macOS support.
std::mem::forget(self.display_link.take());
- unsafe {
- dispatch_source_cancel(self.frame_requests);
- }
+ self.frame_requests.cancel();
+ // A suspended DispatchSource cannot be destroyed.
+ self.frame_requests.resume();
}
}
@@ -24,6 +24,7 @@ use core_foundation::{
string::{CFString, CFStringRef},
};
use ctor::ctor;
+use dispatch2::DispatchQueue;
use futures::channel::oneshot;
use gpui::{
Action, AnyWindowHandle, BackgroundExecutor, ClipboardItem, CursorStyle, ForegroundExecutor,
@@ -493,13 +494,11 @@ impl Platform for MacPlatform {
// this, we make quitting the application asynchronous so that we aren't holding borrows to
// the app state on the stack when we actually terminate the app.
- use crate::dispatcher::{dispatch_get_main_queue, dispatch_sys::dispatch_async_f};
-
unsafe {
- dispatch_async_f(dispatch_get_main_queue(), ptr::null_mut(), Some(quit));
+ DispatchQueue::main().exec_async_f(ptr::null_mut(), quit);
}
- unsafe extern "C" fn quit(_: *mut c_void) {
+ extern "C" fn quit(_: *mut c_void) {
unsafe {
let app = NSApplication::sharedApplication(nil);
let _: () = msg_send![app, terminate: nil];
@@ -1261,19 +1260,13 @@ extern "C" fn on_thermal_state_change(this: &mut Object, _: Sel, _: id) {
// Defer to the next run loop iteration to avoid re-entrant borrows of the App RefCell,
// as NSNotificationCenter delivers this notification synchronously and it may fire while
// the App is already borrowed (same pattern as quit() above).
- use crate::dispatcher::{dispatch_get_main_queue, dispatch_sys::dispatch_async_f};
-
let platform = unsafe { get_mac_platform(this) };
let platform_ptr = platform as *const MacPlatform as *mut c_void;
unsafe {
- dispatch_async_f(
- dispatch_get_main_queue(),
- platform_ptr,
- Some(on_thermal_state_change),
- );
+ DispatchQueue::main().exec_async_f(platform_ptr, on_thermal_state_change);
}
- unsafe extern "C" fn on_thermal_state_change(context: *mut c_void) {
+ extern "C" fn on_thermal_state_change(context: *mut c_void) {
let platform = unsafe { &*(context as *const MacPlatform) };
let mut lock = platform.0.lock();
if let Some(mut callback) = lock.on_thermal_state_change.take() {
@@ -1,7 +1,6 @@
use crate::{
- BoolExt, DisplayLink, MacDisplay, NSRange, NSStringExt, dispatch_get_main_queue,
- dispatcher::dispatch_sys::dispatch_async_f, events::platform_input_from_native, ns_string,
- renderer,
+ BoolExt, DisplayLink, MacDisplay, NSRange, NSStringExt, events::platform_input_from_native,
+ ns_string, renderer,
};
#[cfg(any(test, feature = "test-support"))]
use anyhow::Result;
@@ -22,6 +21,7 @@ use cocoa::{
NSUserDefaults,
},
};
+use dispatch2::DispatchQueue;
use gpui::{
AnyWindowHandle, BackgroundExecutor, Bounds, Capslock, ExternalPaths, FileDropEvent,
ForegroundExecutor, KeyDownEvent, Keystroke, Modifiers, ModifiersChangedEvent, MouseButton,
@@ -1050,34 +1050,32 @@ impl PlatformWindow for MacWindow {
fn merge_all_windows(&self) {
let native_window = self.0.lock().native_window;
- unsafe extern "C" fn merge_windows_async(context: *mut std::ffi::c_void) {
- let native_window = context as id;
- let _: () = msg_send![native_window, mergeAllWindows:nil];
+ extern "C" fn merge_windows_async(context: *mut std::ffi::c_void) {
+ unsafe {
+ let native_window = context as id;
+ let _: () = msg_send![native_window, mergeAllWindows:nil];
+ }
}
unsafe {
- dispatch_async_f(
- dispatch_get_main_queue(),
- native_window as *mut std::ffi::c_void,
- Some(merge_windows_async),
- );
+ DispatchQueue::main()
+ .exec_async_f(native_window as *mut std::ffi::c_void, merge_windows_async);
}
}
fn move_tab_to_new_window(&self) {
let native_window = self.0.lock().native_window;
- unsafe extern "C" fn move_tab_async(context: *mut std::ffi::c_void) {
- let native_window = context as id;
- let _: () = msg_send![native_window, moveTabToNewWindow:nil];
- let _: () = msg_send![native_window, makeKeyAndOrderFront: nil];
+ extern "C" fn move_tab_async(context: *mut std::ffi::c_void) {
+ unsafe {
+ let native_window = context as id;
+ let _: () = msg_send![native_window, moveTabToNewWindow:nil];
+ let _: () = msg_send![native_window, makeKeyAndOrderFront: nil];
+ }
}
unsafe {
- dispatch_async_f(
- dispatch_get_main_queue(),
- native_window as *mut std::ffi::c_void,
- Some(move_tab_async),
- );
+ DispatchQueue::main()
+ .exec_async_f(native_window as *mut std::ffi::c_void, move_tab_async);
}
}
@@ -2252,7 +2250,7 @@ extern "C" fn display_layer(this: &Object, _: Sel, _: id) {
}
}
-unsafe extern "C" fn step(view: *mut c_void) {
+extern "C" fn step(view: *mut c_void) {
let view = view as id;
let window_state = unsafe { get_window_state(&*view) };
let mut lock = window_state.lock();