From ec123482c0fd0920c13044d91ffc13ca785b58d6 Mon Sep 17 00:00:00 2001 From: Paulo Santana Date: Sat, 18 Jan 2025 15:00:20 -0300 Subject: [PATCH] turn global contexts into thread locals --- imgui/src/context.rs | 4 +- imgui/src/docking_utils.rs | 159 ++++++++++++++++++++----------------- 2 files changed, 88 insertions(+), 75 deletions(-) diff --git a/imgui/src/context.rs b/imgui/src/context.rs index 36e785f..f40f6d3 100644 --- a/imgui/src/context.rs +++ b/imgui/src/context.rs @@ -664,7 +664,7 @@ impl Context { backend: Box::new(backend), }; - *crate::PLATFORM_VIEWPORT_BACKEND.lock().unwrap() = Some(ctx); + crate::PLATFORM_VIEWPORT_CONTEXT.with_borrow_mut(|c| *c = Some(ctx)); let pio = self.platform_io_mut(); pio.platform_create_window = Some(docking_utils::platform_create_window); @@ -703,7 +703,7 @@ impl Context { backend: Box::new(backend), }; - *crate::RENDERER_VIEWPORT_BACKEND.lock().unwrap() = Some(ctx); + crate::RENDERER_VIEWPORT_CONTEXT.with_borrow_mut(|c| *c = Some(ctx)); let pio = self.platform_io_mut(); pio.renderer_create_window = Some(docking_utils::renderer_create_window); diff --git a/imgui/src/docking_utils.rs b/imgui/src/docking_utils.rs index e5d0fd3..f5a4650 100644 --- a/imgui/src/docking_utils.rs +++ b/imgui/src/docking_utils.rs @@ -1,17 +1,16 @@ use std::{ - cell::UnsafeCell, + cell::RefCell, ffi::{c_void, CStr}, os::raw::{c_char, c_int}, - sync::Mutex, }; use crate::{PlatformIo, Viewport}; -pub(crate) static PLATFORM_VIEWPORT_BACKEND: Mutex> = - Mutex::new(None); +thread_local!( + pub(crate) static PLATFORM_VIEWPORT_CONTEXT: RefCell> = const { RefCell::new(None) }); -pub(crate) static RENDERER_VIEWPORT_BACKEND: Mutex> = - Mutex::new(None); +thread_local!( + pub(crate) static RENDERER_VIEWPORT_CONTEXT: RefCell> = const { RefCell::new(None) }); /// Trait holding functions needed when the platform integration supports viewports. /// @@ -73,94 +72,108 @@ pub trait PlatformViewportBackend: 'static { ) -> i32; } -/// Used to get the current Contexts [`PlatformViewportContext`]. -fn get_platform_ctx() -> &'static mut PlatformViewportContext { - let a = UnsafeCell::new(PLATFORM_VIEWPORT_BACKEND.lock().unwrap()).get(); - unsafe { (*a).as_mut().unwrap() } +#[inline] +fn get_platform( + ctx: &mut Option, +) -> &mut Box { + &mut ctx.as_mut().unwrap().backend } -/// Used to get the current Contexts [`RendererViewportContext`]. -fn get_renderer_ctx() -> &'static mut RendererViewportContext { - let a = UnsafeCell::new(RENDERER_VIEWPORT_BACKEND.lock().unwrap()).get(); - unsafe { (*a).as_mut().unwrap() } +#[inline] +fn get_renderer( + ctx: &mut Option, +) -> &mut Box { + &mut ctx.as_mut().unwrap().backend } pub(crate) extern "C" fn platform_create_window(viewport: *mut Viewport) { - let ctx = get_platform_ctx(); - ctx.backend.create_window(unsafe { &mut *viewport }); + PLATFORM_VIEWPORT_CONTEXT.with_borrow_mut(|ctx: &mut Option| { + get_platform(ctx).create_window(unsafe { &mut *viewport }); + }) } pub(crate) extern "C" fn platform_destroy_window(viewport: *mut Viewport) { - let ctx = get_platform_ctx(); - ctx.backend.destroy_window(unsafe { &mut *viewport }); + PLATFORM_VIEWPORT_CONTEXT.with_borrow_mut(|ctx| { + get_platform(ctx).destroy_window(unsafe { &mut *viewport }); + }) } + pub(crate) extern "C" fn platform_show_window(viewport: *mut Viewport) { - let ctx = get_platform_ctx(); - ctx.backend.show_window(unsafe { &mut *viewport }); + PLATFORM_VIEWPORT_CONTEXT.with_borrow_mut(|ctx| { + get_platform(ctx).show_window(unsafe { &mut *viewport }); + }) } pub(crate) extern "C" fn platform_set_window_pos(viewport: *mut Viewport, pos: sys::ImVec2) { - let ctx = get_platform_ctx(); - ctx.backend - .set_window_pos(unsafe { &mut *viewport }, [pos.x, pos.y]); + PLATFORM_VIEWPORT_CONTEXT.with_borrow_mut(|ctx| { + get_platform(ctx).set_window_pos(unsafe { &mut *viewport }, [pos.x, pos.y]); + }) } pub(crate) extern "C" fn platform_get_window_pos( viewport: *mut Viewport, out_pos: *mut sys::ImVec2, ) { - let ctx = get_platform_ctx(); - let pos = ctx.backend.get_window_pos(unsafe { &mut *viewport }); - unsafe { - *out_pos = sys::ImVec2::new(pos[0], pos[1]); - } + PLATFORM_VIEWPORT_CONTEXT.with_borrow_mut(|ctx| { + let pos = get_platform(ctx).get_window_pos(unsafe { &mut *viewport }); + unsafe { + *out_pos = sys::ImVec2::new(pos[0], pos[1]); + } + }) } pub(crate) extern "C" fn platform_set_window_size(viewport: *mut Viewport, size: sys::ImVec2) { - let ctx = get_platform_ctx(); - ctx.backend - .set_window_size(unsafe { &mut *viewport }, [size.x, size.y]); + PLATFORM_VIEWPORT_CONTEXT.with_borrow_mut(|ctx| { + get_platform(ctx).set_window_size(unsafe { &mut *viewport }, [size.x, size.y]); + }) } pub(crate) extern "C" fn platform_get_window_size( viewport: *mut Viewport, out_size: *mut sys::ImVec2, ) { - let ctx = get_platform_ctx(); - let size = ctx.backend.get_window_size(unsafe { &mut *viewport }); - unsafe { - *out_size = sys::ImVec2::new(size[0], size[1]); - } + PLATFORM_VIEWPORT_CONTEXT.with_borrow_mut(|ctx: &mut Option| { + let size = get_platform(ctx).get_window_size(unsafe { &mut *viewport }); + unsafe { + *out_size = sys::ImVec2::new(size[0], size[1]); + } + }) } pub(crate) extern "C" fn platform_set_window_focus(viewport: *mut Viewport) { - let ctx = get_platform_ctx(); - ctx.backend.set_window_focus(unsafe { &mut *viewport }); + PLATFORM_VIEWPORT_CONTEXT.with_borrow_mut(|ctx: &mut Option| { + get_platform(ctx).set_window_focus(unsafe { &mut *viewport }); + }) } pub(crate) extern "C" fn platform_get_window_focus(viewport: *mut Viewport) -> bool { - let ctx = get_platform_ctx(); - ctx.backend.get_window_focus(unsafe { &mut *viewport }) + PLATFORM_VIEWPORT_CONTEXT.with_borrow_mut(|ctx: &mut Option| { + get_platform(ctx).get_window_focus(unsafe { &mut *viewport }) + }) } pub(crate) extern "C" fn platform_get_window_minimized(viewport: *mut Viewport) -> bool { - let ctx = get_platform_ctx(); - ctx.backend.get_window_minimized(unsafe { &mut *viewport }) + PLATFORM_VIEWPORT_CONTEXT.with_borrow_mut(|ctx: &mut Option| { + get_platform(ctx).get_window_minimized(unsafe { &mut *viewport }) + }) } pub(crate) extern "C" fn platform_set_window_title(viewport: *mut Viewport, title: *const c_char) { - let ctx = get_platform_ctx(); - let title = unsafe { CStr::from_ptr(title).to_str().unwrap() }; - ctx.backend - .set_window_title(unsafe { &mut *viewport }, title); + PLATFORM_VIEWPORT_CONTEXT.with_borrow_mut(|ctx| { + let title = unsafe { CStr::from_ptr(title).to_str().unwrap() }; + get_platform(ctx).set_window_title(unsafe { &mut *viewport }, title); + }) } pub(crate) extern "C" fn platform_set_window_alpha(viewport: *mut Viewport, alpha: f32) { - let ctx = get_platform_ctx(); - ctx.backend - .set_window_alpha(unsafe { &mut *viewport }, alpha); + PLATFORM_VIEWPORT_CONTEXT.with_borrow_mut(|ctx| { + get_platform(ctx).set_window_alpha(unsafe { &mut *viewport }, alpha); + }) } pub(crate) extern "C" fn platform_update_window(viewport: *mut Viewport) { - let ctx = get_platform_ctx(); - ctx.backend.update_window(unsafe { &mut *viewport }); + PLATFORM_VIEWPORT_CONTEXT.with_borrow_mut(|ctx| { + get_platform(ctx).update_window(unsafe { &mut *viewport }); + }) } pub(crate) extern "C" fn platform_render_window(viewport: *mut Viewport, _arg: *mut c_void) { - let ctx = get_platform_ctx(); - ctx.backend.render_window(unsafe { &mut *viewport }); + PLATFORM_VIEWPORT_CONTEXT.with_borrow_mut(|ctx| { + get_platform(ctx).render_window(unsafe { &mut *viewport }); + }) } pub(crate) extern "C" fn platform_swap_buffers(viewport: *mut Viewport, _arg: *mut c_void) { - let ctx = get_platform_ctx(); - ctx.backend.swap_buffers(unsafe { &mut *viewport }); + PLATFORM_VIEWPORT_CONTEXT.with_borrow_mut(|ctx| { + get_platform(ctx).swap_buffers(unsafe { &mut *viewport }); + }) } pub(crate) extern "C" fn platform_create_vk_surface( viewport: *mut Viewport, @@ -168,11 +181,11 @@ pub(crate) extern "C" fn platform_create_vk_surface( _arg: *const c_void, out_surface: *mut u64, ) -> c_int { - let ctx = get_platform_ctx(); - ctx.backend - .create_vk_surface(unsafe { &mut *viewport }, instance, unsafe { + PLATFORM_VIEWPORT_CONTEXT.with_borrow_mut(|ctx| { + get_platform(ctx).create_vk_surface(unsafe { &mut *viewport }, instance, unsafe { &mut *out_surface }) + }) } /// Just holds a [`PlatformViewportBackend`]. @@ -180,8 +193,6 @@ pub(crate) struct PlatformViewportContext { pub(crate) backend: Box, } -unsafe impl Send for PlatformViewportContext {} - /// Trait that holds optional functions for a rendering backend to support multiple viewports. /// /// It is completely fine to not use this Backend at all, as all functions are optional. @@ -197,25 +208,29 @@ pub trait RendererViewportBackend: 'static { } pub(crate) extern "C" fn renderer_create_window(viewport: *mut Viewport) { - let ctx = get_renderer_ctx(); - ctx.backend.create_window(unsafe { &mut *viewport }); + RENDERER_VIEWPORT_CONTEXT.with_borrow_mut(|ctx| { + get_renderer(ctx).create_window(unsafe { &mut *viewport }); + }) } pub(crate) extern "C" fn renderer_destroy_window(viewport: *mut Viewport) { - let ctx = get_renderer_ctx(); - ctx.backend.destroy_window(unsafe { &mut *viewport }); + RENDERER_VIEWPORT_CONTEXT.with_borrow_mut(|ctx| { + get_renderer(ctx).destroy_window(unsafe { &mut *viewport }); + }) } pub(crate) extern "C" fn renderer_set_window_size(viewport: *mut Viewport, size: sys::ImVec2) { - let ctx = get_renderer_ctx(); - ctx.backend - .set_window_size(unsafe { &mut *viewport }, [size.x, size.y]); + RENDERER_VIEWPORT_CONTEXT.with_borrow_mut(|ctx| { + get_renderer(ctx).set_window_size(unsafe { &mut *viewport }, [size.x, size.y]); + }) } pub(crate) extern "C" fn renderer_render_window(viewport: *mut Viewport, _arg: *mut c_void) { - let ctx = get_renderer_ctx(); - ctx.backend.render_window(unsafe { &mut *viewport }); + RENDERER_VIEWPORT_CONTEXT.with_borrow_mut(|ctx| { + get_renderer(ctx).render_window(unsafe { &mut *viewport }); + }) } pub(crate) extern "C" fn renderer_swap_buffers(viewport: *mut Viewport, _arg: *mut c_void) { - let ctx = get_renderer_ctx(); - ctx.backend.swap_buffers(unsafe { &mut *viewport }); + RENDERER_VIEWPORT_CONTEXT.with_borrow_mut(|ctx| { + get_renderer(ctx).swap_buffers(unsafe { &mut *viewport }); + }) } /// Just holds a [`RendererViewportBackend`]. @@ -223,8 +238,6 @@ pub(crate) struct RendererViewportContext { pub(crate) backend: Box, } -unsafe impl Send for RendererViewportContext {} - /// Describes a monitor that can be used by ImGui. #[repr(C)] pub struct PlatformMonitor {