多线程Wayland客户端实现步骤及移植崩溃问题解决方案
为每个工作线程创建独立事件队列
每个需要处理Wayland事件的线程,必须调用wl_display_create_queue()创建专属的wl_event_queue,绝对不能多个线程共享同一队列,这是线程隔离的基础,能确保每个线程的事件只会被自身处理。将Wayland Proxy绑定到对应线程的事件队列
创建或获取到Wayland对象(如wl_surface、wl_shm等)的proxy后,立即在创建proxy的线程中调用wl_proxy_set_queue(),将其分配给目标线程的事件队列。跨线程操作未初始化的proxy极易引发竞态问题,必须规避。线程内独立调度事件队列
每个工作线程要启动自身的事件循环,调用wl_display_dispatch_queue()或wl_display_dispatch_queue_pending()处理绑定到自身队列的事件。严禁在多个线程中调度同一个队列,这会直接导致崩溃。严格控制跨线程的Wayland对象操作
除非通过互斥锁等线程安全机制保护,否则禁止在proxy所属线程之外调用该proxy的接口。比如某个wl_surface绑定到线程A的队列,那么所有对这个surface的操作(如wl_surface_commit())必须在线程A中执行,或在持有全局锁的前提下执行。谨慎处理全局Wayland对象
wl_display、wl_registry这类全局对象,尽量只在主线程中操作;若必须在其他线程使用,要确保每次访问都持有锁,且不要长时间占用锁影响事件调度效率。线程退出时做好清理
线程退出前,先停止事件调度,再调用wl_event_queue_destroy()销毁自身队列,确保关联的proxy都已正确释放,避免资源泄漏或野指针问题。
参考手册内容:
多线程支持通过为每个额外线程创建一个额外的wl_event_queue来实现,每个对象的事件可以放入特定队列,因此理论上可以让不同线程处理每个创建对象的事件。
一个wl_display至少有一个事件队列,称为主队列。客户端可以使用wl_display_create_queue()创建额外的事件队列,并将wl_proxy分配给该队列。特定proxy发生的事件始终会排入其分配的队列。客户端可以通过将proxy分配给事件队列,并确保仅在满足特定前提(如持有锁或在指定线程中运行)时才调度该队列,来保证proxy事件处理程序被调用时该前提成立。
内容的提问来源于stack exchange,提问作者Haydentech

