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