wl_client/proxy/low_level/
owned.rs

1use {
2    crate::{
3        ffi::{
4            WL_MARSHAL_FLAG_DESTROY, interface_compatible, wl_argument, wl_dispatcher_func_t,
5            wl_interface, wl_message, wl_proxy,
6        },
7        proxy::low_level::{
8            borrowed::UntypedBorrowedProxy,
9            check_dispatching_proxy, check_new_proxy,
10            owned::scope::{Scope, ScopeData},
11        },
12        queue::Queue,
13        utils::sync_ptr::{SyncNonNull, SyncPtr},
14    },
15    destruction::ProxyDataDestruction,
16    parking_lot::Mutex,
17    std::{
18        any::Any,
19        cell::Cell,
20        collections::HashSet,
21        ffi::{c_int, c_void},
22        mem::{self},
23        ops::Deref,
24        panic::{AssertUnwindSafe, catch_unwind},
25        ptr::{self, NonNull},
26        sync::{
27            Arc,
28            atomic::{
29                AtomicBool, AtomicPtr, AtomicUsize,
30                Ordering::{Acquire, Relaxed, Release},
31                fence,
32            },
33        },
34    },
35};
36
37pub(crate) mod destruction;
38pub(crate) mod scope;
39#[cfg(test)]
40mod tests;
41
42/// A owned `wl_proxy` pointer.
43///
44/// Most of the time you will not work with this type directly and instead use one of
45/// the types generated by `wl-client-builder`.
46#[derive(Eq, PartialEq)]
47pub struct UntypedOwnedProxy {
48    data: SyncNonNull<UntypedOwnedProxyData>,
49}
50
51struct UntypedOwnedProxyData {
52    /// This object is owned by a number of [`UntypedOwnedProxy`] objects. This field
53    /// contains the number of these objects. Additionally, if ever_had_event_handler is
54    /// true, then libwayland might be holding a pointer to this object and this object
55    /// must not be destroyed until we know that libwayland has ceased accessing the
56    /// pointer.
57    ref_count: AtomicUsize,
58    /// The queue that this proxy is attached to.
59    queue: Queue,
60    /// This field holds the wl_proxy. We're storing it in a [`UntypedBorrowedProxy`] so
61    /// that we can deref to [`UntypedBorrowedProxy`]. This [`UntypedBorrowedProxy`] is
62    /// mutable. The proxy is a wrapper if and only if `interface` is None.
63    proxy: UntypedBorrowedProxy,
64    /// This is Some if and only if the proxy is not a wrapper. In this case, this is the
65    /// interface of the proxy.
66    interface: Option<&'static wl_interface>,
67    /// This is true if a event handler has been attached to the proxy. We only allow
68    /// attaching a event handler once.
69    ever_had_event_handler: AtomicBool,
70    /// A pointer to event handler data. This is set once while holding the proxy pointer
71    /// read lock. It is accessed by event_handler_func and when destroying the event
72    /// handler. Visibility is ensured just like for the scope_data field below.
73    ///
74    /// The pointer gets invalidated when the event handler is destroyed which can happen
75    /// long before this object is dropped. In these cases, access to the event handler
76    /// is prevented in two ways: If the proxy has been destroyed, then event_handler_func
77    /// is no longer invoked and the code ensures that the event handler is not destroyed
78    /// before the last such invocation has completed. If the proxy has not been destroyed,
79    /// then the event dispatcher is event_handler_func_scoped and that function will
80    /// never again call into event_handler_func.
81    event_handler: AtomicPtr<u8>,
82    /// If this is not null, it is a function pointer to a function that can be used to
83    /// drop the event handler. This field is written at the same time as the
84    /// event_handler field is written. Visibility is ensured just like for event_handler.
85    /// It is set back to null while holding the proxy pointer write lock when creating
86    /// the [`ProxyDataDestruction`] for the event handler.
87    drop_event_handler: AtomicPtr<u8>,
88    /// This field is true if and only if this proxy is attached to a registry.
89    stored_in_registry: AtomicBool,
90    /// The scope that this proxy is attached to, if any. This ensures that the scope_data
91    /// field remains valid until this object is dropped.
92    scope_data_arc: Mutex<Option<Arc<ScopeData>>>,
93    /// A pointer to the data in the Arc stored in scope_data_arc, or null if the proxy is
94    /// not attached to a scope. This field is written at most once while holding the proxy
95    /// pointer read lock. It is accessed by event_handler_func_scoped and by code in this
96    /// file.
97    ///
98    /// The event handler is attached to this proxy while holding the dispatch lock which
99    /// is also held when the event handler is invoked. This ensures visibility in the
100    /// event handler.
101    ///
102    /// All code in this file that accesses this field does so while having exclusive
103    /// access to the proxy pointer, either by holding the proxy pointer write lock or in
104    /// the drop impl. This ensures visibility in those places.
105    ///
106    /// If it is not null, then this pointer remains valid until this object is dropped.
107    scope_data: AtomicPtr<ScopeData>,
108}
109
110/// A registry used for owned proxies that might have to be destroyed at some point.
111///
112/// This is used for proxies that have event handlers with a drop impl. Such event handlers can
113/// form a reference cycle with the proxy that has to be explicitly broken. All proxies
114/// in this registry will be explicitly destroyed when the connection object is dropped.
115/// Destroying the proxy drops the event handler which breaks the reference cycle.
116#[derive(Default)]
117pub(crate) struct OwnedProxyRegistry {
118    /// This set contains proxies that have a event handler with a drop impl attached. The
119    /// pointers in this set are always valid, but they are not strong references. You can
120    /// dereference them while holding this lock. To be able to use them outside of
121    /// holding the lock, you must increment the reference count from n>0 to n+1. Note
122    /// that the reference count can be n=0. Such pointers must be ignored.
123    proxies: Mutex<HashSet<SyncNonNull<UntypedOwnedProxyData>>>,
124}
125
126/// A transparent wrapper around [`UntypedOwnedProxy`].
127///
128/// # Safety
129///
130/// This type must be a transparent wrapper around [`UntypedOwnedProxy`].
131pub unsafe trait UntypedOwnedProxyWrapper: Clone {}
132
133// SAFETY: Self is literally UntypedOwnedProxy.
134unsafe impl UntypedOwnedProxyWrapper for UntypedOwnedProxy {}
135
136impl Deref for UntypedOwnedProxy {
137    type Target = UntypedBorrowedProxy;
138
139    fn deref(&self) -> &Self::Target {
140        &self.data().proxy
141    }
142}
143
144impl UntypedOwnedProxy {
145    /// Creates a new [`UntypedOwnedProxy`] from a plain `wl_proxy`.
146    ///
147    /// # Safety
148    ///
149    /// - `proxy` must be a valid pointer to a plain `wl_proxy`.
150    /// - `proxy` must remain valid for the lifetime of this object and its clones.
151    /// - `proxy` must not have an event handler or dispatcher assigned.
152    /// - `queue` must be the queue of the proxy.
153    /// - `interface` must be the interface of the proxy.
154    pub unsafe fn from_plain_wl_proxy(
155        queue: &Queue,
156        proxy: NonNull<wl_proxy>,
157        interface: &'static wl_interface,
158    ) -> Self {
159        // SAFETY: - proxy is a plain proxy and interface is its interface
160        //         - proxy does not have an event handler assigned
161        //         - queue is the queue of the queue
162        unsafe { Self::new(queue, proxy, Some(interface)) }
163    }
164
165    /// Creates a new [`UntypedOwnedProxy`] from a wrapper `wl_proxy`.
166    ///
167    /// # Safety
168    ///
169    /// - `proxy` must be a valid pointer to a wrapper `wl_proxy`.
170    /// - `proxy` must remain valid for the lifetime of this object and its clones.
171    /// - `queue` must be the queue of the proxy.
172    pub unsafe fn from_wrapper_wl_proxy(queue: &Queue, proxy: NonNull<wl_proxy>) -> Self {
173        // SAFETY: - proxy is a valid wrapper and as such does not have an event handler
174        //         - queue is the queue of the proxy
175        unsafe { Self::new(queue, proxy, None) }
176    }
177
178    /// # Safety
179    ///
180    /// - proxy must be a valid pointer
181    /// - proxy must not have an event handler assigned
182    /// - this function takes ownership of the proxy
183    /// - the proxy's event handler must not be modified except through this object
184    /// - queue must be the queue of the proxy
185    /// - if interface is not None, it must be the interface of the wl_proxy
186    /// - if this is a wrapper, then interface must be None
187    /// - if this is not a wrapper, then interface must not be None
188    unsafe fn new(
189        queue: &Queue,
190        proxy: NonNull<wl_proxy>,
191        interface: Option<&'static wl_interface>,
192    ) -> Self {
193        let data = Box::new(UntypedOwnedProxyData {
194            ref_count: AtomicUsize::new(1),
195            queue: queue.clone(),
196            proxy: {
197                // SAFETY: - By the safety requirements of this function, proxy is a valid
198                //           pointer.
199                //         - Whenever we destroy the proxy we first set it to a null
200                //           pointer.
201                unsafe { UntypedBorrowedProxy::new_internal(queue.libwayland(), proxy) }
202            },
203            interface,
204            ever_had_event_handler: Default::default(),
205            event_handler: Default::default(),
206            drop_event_handler: Default::default(),
207            stored_in_registry: Default::default(),
208            scope_data: Default::default(),
209            scope_data_arc: Default::default(),
210        });
211        Self {
212            data: SyncNonNull(NonNull::from(Box::leak(data))),
213        }
214    }
215
216    fn data(&self) -> &UntypedOwnedProxyData {
217        // SAFETY: self.data is always a valid pointer except during `drop`.
218        unsafe { self.data.as_ref() }
219    }
220
221    /// Destroys this object by sending a request on this proxy.
222    ///
223    /// After this function returns, the underlying `wl_proxy` has been destroyed.
224    ///
225    /// This function cannot be used if the request creates a new object. Use
226    /// [`UntypedOwnedProxy::send_constructor`] for that purpose.
227    ///
228    /// This function cannot be used if this is a wrapper.
229    ///
230    /// # Panic
231    ///
232    /// - This function panics if this proxy has already been destroyed.
233    /// - This function might panic if the proxy is attached to a local queue and the
234    ///   current thread is not the thread in which the queue was created.
235    /// - This function panics if this proxy is a wrapper.
236    ///
237    /// # Safety
238    ///
239    /// - `opcode` must be a valid request opcode for the interface of the proxy.
240    /// - `args` must conform to the interface + opcode of the proxy.
241    /// - `args` must not contain any `new_id` element.
242    #[inline]
243    pub unsafe fn send_destructor(&self, opcode: u32, args: &mut [wl_argument]) {
244        let slf = self.data();
245        if slf.interface.is_none() {
246            panic!("Proxy is a wrapper");
247        }
248        let _write_lock = slf.proxy.lock.write();
249        // SAFETY: We're holding the write lock.
250        let proxy = slf.proxy.proxy.load(Relaxed);
251        let proxy = check_dispatching_proxy(NonNull::new(proxy));
252        // SAFETY: We're holding the write lock.
253        slf.proxy.proxy.store(ptr::null_mut(), Relaxed);
254        // SAFETY: - We've just checked that proxy is not null. By the invariants, the
255        //           proxy is valid.
256        //         - The opcode/args requirements are forwarded to the caller.
257        //         - Flags are WL_MARSHAL_FLAG_DESTROY.
258        //         - We've checked above that the proxy is not a wrapper.
259        //         - We've set the proxy pointer to null.
260        unsafe {
261            slf.proxy.libwayland.wl_proxy_marshal_array_flags(
262                proxy.as_ptr(),
263                opcode,
264                ptr::null(),
265                0,
266                WL_MARSHAL_FLAG_DESTROY,
267                args.as_mut_ptr(),
268            );
269        }
270        // SAFETY: - We're holding the write lock of the proxy.
271        //         - The proxy has been destroyed.
272        unsafe {
273            self.destroy_event_handler();
274        }
275    }
276
277    /// Creates a new object by sending a request on this proxy.
278    ///
279    /// If `DESTROY=true`, then the underlying `wl_proxy` has been destroyed after this
280    /// function returns.
281    ///
282    /// This function can only be used if the request creates a new object. Use
283    /// [`UntypedOwnedProxy::send_destructor`] or [`UntypedBorrowedProxy::send_request`]
284    /// otherwise.
285    ///
286    /// The new object will be attached to the queue of this proxy.
287    ///
288    /// # Panic
289    ///
290    /// - This function panics if this proxy has already been destroyed.
291    /// - If `DESTROY=true`, then this function might panic if the proxy is attached to a
292    ///   local queue and the current thread is not the thread in which the queue was
293    ///   created.
294    /// - If `DESTROY=true`, then this function panics if this proxy is a wrapper.
295    ///
296    /// # Safety
297    ///
298    /// - `opcode` must be a valid request opcode for the interface of the proxy.
299    /// - `args` must conform to the interface + opcode of the proxy.
300    /// - `args` must contain exactly one `new_id` element.
301    /// - `interface` must be a valid `wl_interface`.
302    pub unsafe fn send_constructor<const DESTROY: bool>(
303        &self,
304        opcode: u32,
305        args: &mut [wl_argument],
306        interface: &'static wl_interface,
307        version: Option<u32>,
308    ) -> Self {
309        let slf = self.data();
310        let (_read_lock, _write_lock);
311        if DESTROY {
312            if slf.interface.is_none() {
313                panic!("Proxy is a wrapper");
314            }
315            _write_lock = slf.proxy.lock.write();
316        } else {
317            _read_lock = slf.proxy.lock.read_recursive();
318        }
319        // SAFETY: We're holding at least a read lock.
320        let proxy = slf.proxy.proxy.load(Relaxed);
321        let proxy = check_dispatching_proxy(NonNull::new(proxy));
322        let version = version.unwrap_or_else(|| {
323            // SAFETY: - We're holding at least a read lock which ensures that the pointer
324            //           stays valid.
325            //         - We've just checked that the pointer is valid.
326            unsafe { slf.proxy.libwayland.wl_proxy_get_version(proxy.as_ptr()) }
327        });
328        let mut flags = 0;
329        if DESTROY {
330            flags |= WL_MARSHAL_FLAG_DESTROY;
331            // SAFETY: We're holding the write lock.
332            slf.proxy.proxy.store(ptr::null_mut(), Relaxed);
333        }
334        // SAFETY: - We've just checked that proxy is not null. By the invariants, the
335        //           proxy is valid.
336        //         - The opcode/args requirements are forwarded to the caller.
337        //         - Flags are 0 or WL_MARSHAL_FLAG_DESTROY.
338        //         - If flags contains WL_MARSHAL_FLAG_DESTROY then we've checked above
339        //           that the proxy is not a wrapper and we've set the proxy pointer to
340        //           null.
341        let new_proxy = unsafe {
342            slf.proxy.libwayland.wl_proxy_marshal_array_flags(
343                proxy.as_ptr(),
344                opcode,
345                interface,
346                version,
347                flags,
348                args.as_mut_ptr(),
349            )
350        };
351        if DESTROY {
352            // SAFETY: - We're holding the write lock of the proxy.
353            //         - The proxy has been destroyed.
354            unsafe {
355                self.destroy_event_handler();
356            }
357        }
358        let new_proxy = check_new_proxy(new_proxy);
359        // SAFETY: - new_proxy was returned by libwayland and we've just checked that it
360        //           is not null
361        //         - we're passing ownership
362        //         - proxy was just created so it doesn't have a dispatcher
363        //         - wl_proxy_marshal_array_flags attaches new proxy to the same queue as
364        //           the input proxy
365        //         - wl_proxy_marshal_array_flags sets the interface of the proxy to the
366        //           interface passed into the function
367        unsafe { UntypedOwnedProxy::from_plain_wl_proxy(&slf.queue, new_proxy, interface) }
368    }
369
370    pub(crate) fn set_event_handler<T>(&self, handler: T)
371    where
372        T: EventHandler + Send + 'static,
373    {
374        // SAFETY: T implements Send.
375        unsafe {
376            self.set_event_handler2(handler);
377        }
378    }
379
380    pub(crate) fn set_event_handler_local<T>(&self, handler: T)
381    where
382        T: EventHandler + 'static,
383    {
384        if self.data().queue.is_non_local() {
385            panic!("Queue is not a local queue");
386        }
387        // SAFETY: We've just checked that the queue is thread local.
388        unsafe {
389            self.set_event_handler2(handler);
390        }
391    }
392
393    /// # Safety
394    ///
395    /// If T does not implement Send, then the queue must be a local queue.
396    unsafe fn set_event_handler2<T>(&self, event_handler: T)
397    where
398        T: EventHandler + 'static,
399    {
400        let (event_handler, drop_event_handler) = box_event_handler(event_handler);
401        // SAFETY: - all requirements except the callability of event_handler_func are
402        //           trivially satisfied
403        //         - libwayland only ever calls event handlers while preserving a
404        //           valid pointer to the proxy and all pointers in args
405        //         - set_event_handler3 checks that the interface of the proxy is
406        //           T::WL_INTERFACE
407        //         - libwayland ensures that opcode and args conform to the
408        //           interface before calling the event handler
409        //         - set_event_handler3 sets event_handler to a pointer to T
410        //         - we only ever invalidate the self.event_handler or self.data
411        //           pointers while the queue is idle and after having destroyed
412        //           the proxy.
413        //         - if T is not Send, then this function requires that this is a
414        //           local queue which will panic when trying to call this function
415        //           or any dispatching function on a thread other than the thread
416        //           on which the queue was created
417        //         - we always hold the queue lock while dispatching
418        unsafe {
419            self.set_event_handler3(
420                T::WL_INTERFACE,
421                event_handler,
422                drop_event_handler,
423                mem::needs_drop::<T>(),
424                event_handler_func::<T>,
425                None,
426            );
427        }
428    }
429
430    /// # Safety
431    ///
432    /// There must be a type `T: EventHandler` such that
433    ///
434    /// - interface is T::WL_INTERFACE
435    /// - event_handler is a pointer to a T
436    /// - if T does not implement Send, then the queue must be a local queue
437    /// - event_handler must stay valid until drop_event handler is called
438    /// - drop_event_handler is a pointer to a unsafe fn(*mut u8)
439    ///   that can be called once with event_handler
440    /// - the safety requirements of event_handler_func must be satisfied whenever it is
441    ///   called
442    /// - if scope is Some, then either
443    ///   - the event handler must be destroyed before the end of 'scope, OR
444    ///   - ScopeData::handle_destruction must never run the destructions
445    unsafe fn set_event_handler3<'scope>(
446        &self,
447        interface: &'static wl_interface,
448        event_handler: *mut u8,
449        drop_event_handler: *mut u8,
450        needs_drop: bool,
451        event_handler_func: wl_dispatcher_func_t,
452        scope: Option<&'scope Scope<'scope, '_>>,
453    ) {
454        let slf = self.data();
455        match slf.interface {
456            None => panic!("Proxy is a wrapper"),
457            Some(i) => {
458                // SAFETY: EventHandler::WL_INTERFACE and slf.interface are always valid
459                //         interfaces.
460                let compatible = unsafe { interface_compatible(i, interface) };
461                if !compatible {
462                    panic!("Proxy has an incompatible interface");
463                }
464            }
465        }
466        let lock = slf.proxy.lock();
467        let proxy = check_dispatching_proxy(lock.wl_proxy());
468        if slf.ever_had_event_handler.swap(true, Relaxed) {
469            panic!("Proxy already has an event handler");
470        }
471        if let Some(scope) = scope {
472            *slf.scope_data_arc.lock() = Some(scope.data.clone());
473            slf.scope_data
474                .store(ptr::from_ref(&*scope.data).cast_mut(), Relaxed);
475        }
476        if needs_drop {
477            slf.stored_in_registry.store(true, Relaxed);
478            // SAFETY: - self.data is only ever invalidated via self.create_destruction which
479            //           will remove self.data from the registry.
480            //         - we just wrote to the scope_data field in this thread.
481            unsafe {
482                self.modify_owned_registry(|r| {
483                    r.insert(self.data);
484                });
485            }
486        }
487        slf.event_handler.store(event_handler, Relaxed);
488        slf.drop_event_handler.store(drop_event_handler, Relaxed);
489        slf.queue.run_locked(|| {
490            // SAFETY: - we're holding the proxy lock so the proxy is valid
491            //         - we're holding the queue lock which is always held when
492            //           accessing/modifying the unprotected fields of the wl_proxy
493            //         - by the safety requirements of this function, the safety
494            //           requirements of event_handler_func are satisfied whenever it is
495            //           called
496            unsafe {
497                slf.proxy.libwayland.wl_proxy_add_dispatcher(
498                    proxy.as_ptr(),
499                    Some(event_handler_func),
500                    self.data.as_ptr() as *mut c_void,
501                    ptr::null_mut(),
502                );
503            }
504        });
505    }
506
507    /// Returns the queue of this proxy.
508    ///
509    /// This is the same queue that was passed into the constructor of this object.
510    #[inline]
511    pub fn queue(&self) -> &Queue {
512        &self.data().queue
513    }
514
515    /// Destroys a proxy without sending a wayland message.
516    ///
517    /// This function only destroys the proxy in libwayland without sending a message to the
518    /// compositor.
519    ///
520    /// # Panic
521    ///
522    /// This function might panic if the proxy is attached to a local queue and the current
523    /// thread is not the thread in which the queue was created.
524    #[inline]
525    pub fn destroy(&self) {
526        let slf = self.data();
527        let _lock = slf.proxy.lock.write();
528        if slf.proxy.proxy.load(Relaxed).is_null() {
529            return;
530        }
531        // SAFETY: We're holding the write lock.
532        unsafe {
533            self.destroy_proxy();
534        }
535        // SAFETY: - We're holding the write lock of the proxy.
536        //         - The proxy has been destroyed.
537        unsafe {
538            self.destroy_event_handler();
539        }
540    }
541
542    /// Destroys the proxy if it is not already destroyed.
543    ///
544    /// # Safety
545    ///
546    /// - The caller must have exclusive access to the proxy pointer.
547    unsafe fn destroy_proxy(&self) {
548        let slf = self.data();
549        // SAFETY: By the requirements of this function we have exclusive access to the
550        //         pointer.
551        let proxy = slf.proxy.proxy.load(Relaxed);
552        if proxy.is_null() {
553            return;
554        }
555        // SAFETY: By the requirements of this function we have exclusive access to the
556        //         pointer.
557        slf.proxy.proxy.store(ptr::null_mut(), Relaxed);
558        if slf.interface.is_none() {
559            // SAFETY: - By the requirements of the function, we have exclusive write
560            //           access to the pointer.
561            //         - We've just checked that the pointer is not null. By the
562            //           invariants of UntypedBorrowedProxy, this means that the pointer
563            //           is valid.
564            //         - By the invariants of this type, since the interface is None,
565            //           the proxy is a wrapper.
566            unsafe {
567                slf.proxy.libwayland.wl_proxy_wrapper_destroy(proxy.cast());
568            }
569        } else {
570            // SAFETY: - By the requirements of the function, we have exclusive write
571            //           access to the pointer.
572            //         - We've just checked that the pointer is not null. By the
573            //           invariants of UntypedBorrowedProxy, this means that the pointer
574            //           is valid.
575            //         - By the invariants of this type, since the interface is Some,
576            //           the proxy is not a wrapper.
577            unsafe {
578                slf.proxy.libwayland.wl_proxy_destroy(proxy);
579            }
580        }
581    }
582
583    /// Creates a [`ProxyDataDestruction`] destroying parts of this object.
584    ///
585    /// If the proxy has an event handler with a Drop impl attached, the destruction will
586    /// drop that event handler.
587    ///
588    /// If `destroy_proxy_data` is true, then the destruction will destroy the
589    /// [`UntypedOwnedProxyData`].
590    ///
591    /// # Safety
592    ///
593    /// - The caller must have exclusive access to the proxy pointer.
594    unsafe fn create_destruction(&self, destroy_proxy_data: bool) -> ProxyDataDestruction {
595        let slf = self.data();
596        let data = destroy_proxy_data.then_some(self.data);
597        let drop_event_handler = {
598            // SAFETY: - By the safety requirements of this function, the caller has
599            //           exclusive access to the proxy pointer which ensures visibility
600            //           of the drop_event_handler and event_handler fields.
601            let drop_event_handler = slf.drop_event_handler.load(Relaxed);
602            if drop_event_handler.is_null() {
603                None
604            } else {
605                slf.drop_event_handler.store(ptr::null_mut(), Relaxed);
606                Some((
607                    SyncPtr(slf.event_handler.load(Relaxed)),
608                    SyncPtr(drop_event_handler),
609                ))
610            }
611        };
612        let destruction = ProxyDataDestruction::new(data, drop_event_handler);
613        if slf.stored_in_registry.load(Relaxed) {
614            // SAFETY: - We've just created a destruction fo the event handler if it exists.
615            //         - By the safety requirements of this function, the caller has
616            //           exclusive access to the proxy pointer.
617            unsafe {
618                self.modify_owned_registry(|r| {
619                    r.remove(&self.data);
620                });
621            }
622            slf.stored_in_registry.store(false, Relaxed);
623        }
624        destruction
625    }
626
627    /// # Safety
628    ///
629    /// - All pointers in the registry must be valid.
630    /// - If a proxy has an event handler, it must not be removed from the registry before
631    ///   a destruction has been created for the event handler.
632    /// - The caller must have exclusive access to the proxy pointer or must ensure that
633    ///   writes to the scope_data field happen before this call.
634    unsafe fn modify_owned_registry(
635        &self,
636        f: impl FnOnce(&mut HashSet<SyncNonNull<UntypedOwnedProxyData>>),
637    ) {
638        // SAFETY: The requirement is forwarded to the caller.
639        let scope = unsafe { self.scope() };
640        let mut registry = if let Some(scope) = scope {
641            scope.registry.proxies.lock()
642        } else {
643            self.data().queue.owned_proxy_registry().proxies.lock()
644        };
645        f(&mut registry)
646    }
647
648    /// # Safety
649    ///
650    /// - This must only be called from `drop` once the ref count reaches 0.
651    /// - The effects of other threads must have been made visible.
652    #[inline(never)]
653    unsafe fn drop_slow(&self) {
654        // SAFETY: Since the ref count has reached 0, there are no longer any accessible
655        //         UntypedOwnedProxy referring to the UntypedOwnedProxyData. Since the
656        //         UntypedOwnedProxyData contains the UntypedBorrowedProxy by value, there can
657        //         be no other references to the proxy pointer.
658        unsafe {
659            self.destroy_proxy();
660        }
661        // SAFETY: We have exclusive access to the proxy pointer.
662        let destruction = unsafe { self.create_destruction(true) };
663        let slf = self.data();
664        // SAFETY: We have exclusive access to the proxy pointer.
665        let scope = unsafe { self.scope() };
666        if let Some(scope) = scope {
667            let _scope = slf.scope_data_arc.lock().clone();
668            // SAFETY: - scope() returns the scope that this proxy is attached to.
669            //         - If the destruction contains an event handler, then, by the safety
670            //           requirements of set_event_handler3, we know that
671            //           - we are either within 'scope since otherwise
672            //             destroy_event_handler would have been called and consumed the
673            //             event handler earlier, OR
674            //           - handle_destruction is a no-op.
675            //           If handle_destruction never runs any of the destructions, there
676            //           is nothing to show. Otherwise running the drop impl of the event
677            //           handler is safe as soon as it is no longer referenced anywhere
678            //           since the event handler outlives 'scope.
679            //         - Since the proxy is destroyed, once there are no ongoing
680            //           dispatches, there wont ever again be any dispatches.
681            //         - The _scope variable above ensures that the scope remains valid
682            //           for the duration of the function call.
683            unsafe {
684                scope.handle_destruction(destruction);
685            }
686        } else if slf.ever_had_event_handler.load(Relaxed) {
687            let queue = slf.queue.clone();
688            // SAFETY: - We've just destroyed the proxy above.
689            //         - By the invariants, the proxy is attached to slf.queue.
690            //         - When the queue runs the destruction, no dispatches will be
691            //           running and all subsequent dispatches will happen after this line
692            //           of code.
693            //         - Therefore, libwayland will see that we've destroyed the proxy and
694            //           will not call into the event handler.
695            unsafe {
696                queue.run_destruction_on_idle(destruction);
697            }
698        } else {
699            // SAFETY: - If ever_had_event_handler is false, then neither the queue nor
700            //           libwayland ever had a reference to this object.
701            unsafe {
702                destruction.run();
703            }
704        }
705    }
706
707    /// # Safety
708    ///
709    /// - The caller must have exclusive access to the proxy pointer.
710    /// - If the proxy is not yet destroyed then it must have a scope and the event
711    ///   handler must not be dispatched again.
712    #[inline(never)]
713    unsafe fn destroy_event_handler(&self) {
714        // SAFETY: By the safety requirements of this function, we have exclusive access
715        //         to the proxy pointer.
716        let destruction = unsafe { self.create_destruction(false) };
717        if destruction.is_noop() {
718            return;
719        }
720        // SAFETY: By the safety requirements of this function, we have exclusive access
721        //         to the proxy pointer.
722        let scope = unsafe { self.scope() };
723        if let Some(scope) = scope {
724            // SAFETY: - scope() returns the scope that this proxy is attached to.
725            //         - Since the destruction is not a no-op, we know that this is the
726            //           first call to destroy_event_handler.
727            //         - By the safety requirements of set_event_handler3, we know that
728            //           either we are within 'scope or the destruction is never run. If
729            //           the destruction is never run, then there is nothing to show.
730            //           Otherwise, since the event handler outlives 'scope, calling its
731            //           drop impl is safe if it is no longer reference anywhere.
732            //         - If the proxy is destroyed, then, once there are no ongoing
733            //           dispatches, there wont ever again be any dispatches.
734            //         - Otherwise, since the event handler is never again dispatched, once
735            //           there are no ongoing dispatches, it is safe to destroy it.
736            unsafe {
737                scope.handle_destruction(destruction);
738            }
739        } else {
740            // SAFETY: - This function requires that the proxy is already destroyed.
741            //         - By the invariants, the proxy is attached to self.data().queue.
742            //         - When the queue runs the destruction, no dispatches will be
743            //           running and all subsequent dispatches will happen after this line
744            //           of code.
745            //         - Therefore, libwayland will see that we've destroyed the proxy and
746            //           will not call into the event handler.
747            //         - This call cannot possibly invalidate self.data, even if dropping the
748            //           event handler recursively drops an UntypedOwnedProxy, since we're holding
749            //           on to an UntypedOwnedProxy. Therefore self.data().queue remains valid
750            //           for the function call.
751            unsafe {
752                self.data().queue.run_destruction_on_idle(destruction);
753            }
754        }
755    }
756
757    /// # Safety
758    ///
759    /// - The caller must have exclusive access to the proxy pointer or must ensure that
760    ///   writes to the scope_data field happen before this call.
761    unsafe fn scope(&self) -> Option<&ScopeData> {
762        NonNull::new(self.data().scope_data.load(Relaxed)).map(|s| {
763            // SAFETY: See the documentation of scope_data for why this is safe.
764            unsafe { s.as_ref() }
765        })
766    }
767}
768
769impl Clone for UntypedOwnedProxy {
770    fn clone(&self) -> Self {
771        let slf = self.data();
772        if slf.ref_count.fetch_add(1, Relaxed) > usize::MAX / 2 {
773            std::process::abort();
774        }
775        Self { data: self.data }
776    }
777}
778
779impl Drop for UntypedOwnedProxy {
780    #[inline]
781    fn drop(&mut self) {
782        let slf = self.data();
783        if slf.ref_count.fetch_sub(1, Release) == 1 {
784            fence(Acquire);
785            // SAFETY: - we're in the drop impl
786            //         - the acquire fence ensures visibility
787            unsafe {
788                self.drop_slow();
789            }
790        }
791    }
792}
793
794impl OwnedProxyRegistry {
795    /// Destroys all proxies in this registry.
796    pub(crate) fn destroy_all(&self) {
797        for proxy in self.get_todos() {
798            proxy.destroy();
799        }
800    }
801
802    /// # Safety
803    ///
804    /// - All proxies in the registry must belong to a single scope.
805    /// - We must be within the lifetime of the scope.
806    /// - The queue lock must be held.
807    /// - For all of the event handlers attached to proxies in the registry:
808    ///   - The event handlers must not current be being dispatched.
809    ///   - The event handlers must not be dispatched in the future.
810    unsafe fn destroy_event_handlers(&self) {
811        for proxy in self.get_todos() {
812            let _write_lock = proxy.lock.write();
813            // SAFETY: - We're holding the write lock of the proxy.
814            //         - By the safety requirements of this function, the event handlers
815            //           are currently not being dispatched and will not be dispatched in
816            //           the future.
817            unsafe {
818                proxy.destroy_event_handler();
819            }
820        }
821    }
822
823    fn get_todos(&self) -> Vec<UntypedOwnedProxy> {
824        let proxies = &mut *self.proxies.lock();
825        self.get_todos_locked(proxies)
826    }
827
828    fn get_todos_locked(
829        &self,
830        proxies: &mut HashSet<SyncNonNull<UntypedOwnedProxyData>>,
831    ) -> Vec<UntypedOwnedProxy> {
832        let mut todo = Vec::with_capacity(proxies.len());
833        for proxy in &*proxies {
834            // SAFETY: By the invariants, all pointers in the hash set are valid.
835            let data = unsafe { &*proxy.as_ptr() };
836            let mut ref_count = data.ref_count.load(Relaxed);
837            while ref_count != 0 {
838                if ref_count > usize::MAX / 2 {
839                    std::process::abort();
840                }
841                let res = data.ref_count.compare_exchange_weak(
842                    ref_count,
843                    ref_count + 1,
844                    Relaxed,
845                    Relaxed,
846                );
847                match res {
848                    Ok(_) => {
849                        // SAFETY: We've just acquire a strong reference.
850                        todo.push(UntypedOwnedProxy { data: *proxy });
851                        break;
852                    }
853                    Err(c) => ref_count = c,
854                }
855            }
856        }
857        *proxies = HashSet::default();
858        todo
859    }
860}
861
862/// An event handler that can handle raw libwayland events.
863///
864/// # Safety
865///
866/// - `WL_INTERFACE` must be a valid wl_interface.
867pub unsafe trait EventHandler {
868    /// The type of interface that can be handled by this event handler.
869    const WL_INTERFACE: &'static wl_interface;
870
871    /// Dispatches a raw libwayland event.
872    ///
873    /// # Safety
874    ///
875    /// - `slf` must have an interface compatible with `WL_INTERFACE`.
876    /// - `opcode` and `args` must conform to an event of `WL_INTERFACE`.
877    /// - Any objects contained in `args` must remain valid for the duration of the call.
878    unsafe fn handle_event(
879        &self,
880        queue: &Queue,
881        slf: &UntypedBorrowedProxy,
882        opcode: u32,
883        args: *mut wl_argument,
884    );
885}
886
887fn box_event_handler<T>(event_handler: T) -> (*mut u8, *mut u8) {
888    let event_handler = Box::into_raw(Box::new(event_handler)).cast();
889    let drop_event_handler = {
890        unsafe fn drop<T>(event_handler: *mut u8) {
891            // SAFETY: This function is called only to drop the event_handler boxed above.
892            unsafe {
893                let _ = Box::from_raw(event_handler.cast::<T>());
894            }
895        }
896        drop::<T> as *mut u8
897    };
898    (event_handler, drop_event_handler)
899}
900
901/// The event handler function.
902///
903/// This function is called by libwayland when dispatching an event for the proxy. This
904/// function is only called when the proxy's queue is explicitly being dispatched.
905///
906/// # Safety
907///
908/// - target must be a valid wl_proxy pointer
909/// - the interface of target must be compatible with T::WL_INTERFACE
910/// - event_handler_data must be a pointer to UntypedOwnedProxyData
911/// - the event_handler field in the UntypedOwnedProxy must contain a pointer to T
912/// - opcode and args must conform to T::WL_INTERFACE
913/// - all pointers must remain valid for the duration of this function call
914/// - the previous point includes pointers inside args
915/// - if T is not `Send`, then the current thread must be the thread on which the
916///   event handler was attached
917/// - the queue lock of the proxy must be held
918unsafe extern "C" fn event_handler_func<T>(
919    event_handler_data: *const c_void,
920    target: *mut c_void,
921    opcode: u32,
922    _msg: *const wl_message,
923    args: *mut wl_argument,
924) -> c_int
925where
926    T: EventHandler,
927{
928    // SAFETY: By the safety requirements of this function, event_handler is a valid pointer
929    //         to UntypedOwnedProxyData.
930    let proxy_data = unsafe { &*(event_handler_data as *const UntypedOwnedProxyData) };
931    // SAFETY: Dito, target is and stays valid.
932    let target = unsafe { NonNull::new_unchecked(target.cast()) };
933    // SAFETY: Dito, target is and stays valid.
934    let target =
935        unsafe { UntypedBorrowedProxy::new_immutable(proxy_data.proxy.libwayland, target) };
936    let event_handler = proxy_data.event_handler.load(Relaxed).cast::<T>();
937    // SAFETY: - Dito, event_handler is a valid pointer to T
938    //         - Dito, this function is never called concurrently, therefore it doesn't matter if
939    //           T implements Sync.
940    //         - Dito, if T does not implement Send, then we're creating this reference only in the
941    //           same thread on which the event_handler was attached.
942    let event_handler = unsafe { &*event_handler };
943    let res = catch_unwind(AssertUnwindSafe(|| {
944        // SAFETY: Dito, the interface of target is compatible with T::WL_INTERFACE
945        //         Dito, target is a valid pointer and stays valid
946        //         Dito, opcode and args conform to T::WL_INTERFACE
947        unsafe {
948            event_handler.handle_event(&proxy_data.queue, &target, opcode, args);
949        }
950    }));
951    if let Err(e) = res {
952        DISPATCH_PANIC.set(Some(e));
953    }
954    0
955}
956
957thread_local! {
958    pub(crate) static DISPATCH_PANIC: Cell<Option<Box<dyn Any + Send>>> = const { Cell::new(None) };
959}