资讯动态

Linux PipeWire深度解析之pw_thread_loop_wait调用流程与实战(八十八)

发布时间:2026/8/30 6:38:02 来源:尧图企业网站定制
简介CSDN博客专家、《Android系统多媒体进阶实战》作者博主新书推荐《Android系统多媒体进阶实战》Android Audio工程师专栏地址Audio工程师进阶系列【原创干货持续更新中……】Android多媒体专栏地址多媒体系统工程师系列【原创干货持续更新中……】专题一 二AAOS车载系统AOSP14系统攻城狮入门视频实战课专题三Android14 Binder之HIDL与AIDL通信实战课专题四Android15快速自定义与集成音效实战课专题五Android15音频策略实战课专题六Android15音频性能实战课(无声/杂音/断音/爆音实战案例)人生格言人生从来没有捷径只有行动才是治疗恐惧和懒惰的唯一良药.更多原创,欢迎关注Android系统攻城狮文章目录1.前言要点概括2.应用场景与用法函数原型参数说明返回值应用场景3.调用流程剖析3.1核心步骤3.2调用流程图3.3生命周期图4.实战应用案例5.一句话总结1.前言本篇目的Linux PipeWire深度解析之pw_thread_loop_signal调用流程与实战。要点概括核心功能唤醒正在pw_thread_loop_wait中等待条件变化的线程。工作机制基于Thread Loop内部条件变量发送通知并可通过wait_for_accept参数等待对端调用pw_thread_loop_accept完成确认。典型用途跨线程同步PipeWireStream状态、等待Core连接结果、等待Registry事件、等待异步操作完成。pw_thread_loop_signal的本质不是“触发PipeWire事件循环执行任务”而是“通知等待线程某个共享条件已经发生变化”。它通常和pw_thread_loop_lock、pw_thread_loop_wait、pw_thread_loop_accept配合使用用来在业务线程和PipeWireLoop线程之间建立同步点。它不负责创建线程不负责启动Loop也不负责直接执行回调。Thread Loop的运行由pw_thread_loop_start负责事件分发由内部pw_loop负责signal只解决“等待方什么时候继续往下走”的问题。它和pw_thread_loop_wait是一对接口。wait负责阻塞等待signal负责唤醒等待。它和pw_thread_loop_accept也不同accept只用于确认signal已经被等待方接收通常配合wait_for_accepttrue使用。它和pw_loop_invoke也不同pw_loop_invoke用于把任务投递到Loop线程执行而pw_thread_loop_signal只是线程同步通知。2.应用场景与用法pw_thread_loop_signal是PipeWireThread Loop API中用于唤醒等待线程的接口。它位于PipeWire客户端多线程模型的同步路径中。应用使用pw_thread_loop_new创建Thread Loop后可以把PipeWireContext、Core、Stream等对象放在该Thread Loop中运行。业务线程需要等待某个异步状态变化时通常先持有Thread Loop锁再调用pw_thread_loop_wait进入等待当状态回调或其他线程更新共享状态后再调用pw_thread_loop_signal唤醒等待方。pw_thread_loop_signal用于唤醒正在pw_thread_loop_wait中等待的线程。函数原型voidpw_thread_loop_signal(structpw_thread_loop*loop,bool wait_for_accept);参数说明structpw_thread_loop*loop;loop表示Thread Loop对象。该对象通常由pw_thread_loop_new创建并通过pw_thread_loop_start启动。调用pw_thread_loop_signal时应用一般已经持有Thread Loop锁避免共享状态更新和等待条件检查之间出现竞态。bool wait_for_accept;wait_for_accept表示是否等待对端确认。当该参数为false时pw_thread_loop_signal发送通知后立即返回。调用方不关心等待方是否已经处理该通知。当该参数为true时pw_thread_loop_signal会等待对端调用pw_thread_loop_accept。这个模式适合需要同步确认的场景例如调用方必须确认等待线程已经观察到状态变化后才能继续执行。返回值该函数没有返回值。void调用完成只表示signal动作已经执行。它不表示PipeWire对象状态一定已经切换成功也不表示异步操作一定已经完成。真正的完成条件应由应用自己的共享状态变量判断例如connected、done、error、ready等标志。应用场景第一类场景是等待Stream状态变化。应用创建pw_stream后连接过程是异步的。业务线程可以等待state_changed回调更新状态当回调收到目标状态后调用pw_thread_loop_signal唤醒业务线程。第二类场景是等待Core连接完成。PipeWire客户端连接Core后部分信息需要通过事件回调返回。业务线程可以进入wait状态回调线程收到结果后设置标志并signal。第三类场景是等待Registry枚举完成。客户端需要枚举Node、Device、Port、Factory等全局对象时可以在registry_global回调中收集对象在同步点到达后signal等待方继续执行。第四类场景是控制线程和Loop线程同步退出。应用关闭时控制线程可以设置退出标志并signal等待方等待方检查退出条件后跳出等待流程避免Thread Loop销毁时仍有线程阻塞。3.调用流程剖析3.1核心步骤1.应用调用pw_thread_loop_new创建Thread Loop对象。2.应用调用pw_thread_loop_start启动后台Loop线程。3.业务线程调用pw_thread_loop_lock持有Thread Loop锁。4.业务线程检查共享状态变量如果条件未满足则调用pw_thread_loop_wait进入等待。5.等待期间pw_thread_loop_wait会释放锁使Loop线程或其他线程可以继续更新共享状态。6.状态回调或控制线程更新共享状态例如ready、done、error、connected等。7.状态更新方调用pw_thread_loop_signal通知等待线程。8.等待线程被唤醒后重新获得Thread Loop锁。9.等待线程再次检查共享状态确认条件是否满足。10.如果signal方设置wait_for_accepttrue等待线程处理完成后调用pw_thread_loop_accept确认接收。11.signal方收到accept确认后继续执行。12.业务线程处理完成后调用pw_thread_loop_unlock释放锁。3.2调用流程图3.3生命周期图4.实战应用案例下面以“等待Stream进入目标状态”为例说明pw_thread_loop_signal在真实PipeWire客户端中的用法。应用创建Stream后pw_stream_connect不会把所有状态同步返回给调用方。Stream状态变化会通过state_changed事件回调通知应用。业务线程如果需要等待Stream连接成功或失败就可以使用Thread Loop同步机制。structapp_data{structpw_thread_loop*loop;structpw_stream*stream;enumpw_stream_statestate;interror;bool done;};应用先定义共享状态。state记录Stream当前状态error记录错误码done表示等待条件是否完成。staticvoidon_stream_state_changed(void*userdata,enumpw_stream_stateold,enumpw_stream_statestate,constchar*error){structapp_data*appuserdata;app-statestate;if(statePW_STREAM_STATE_STREAMING||statePW_STREAM_STATE_PAUSED){app-donetrue;pw_thread_loop_signal(app-loop,false);}elseif(statePW_STREAM_STATE_ERROR){app-error-1;app-donetrue;pw_thread_loop_signal(app-loop,false);}}state_changed回调中只做三件事。第一记录最新Stream状态。第二判断是否达到业务线程等待的目标条件。第三调用pw_thread_loop_signal唤醒等待线程。这里使用wait_for_acceptfalse因为业务线程只需要被唤醒后重新检查状态不要求回调线程等待业务线程确认。staticintwait_stream_ready(structapp_data*app){intres0;pw_thread_loop_lock(app-loop);while(!app-done)pw_thread_loop_wait(app-loop);if(app-statePW_STREAM_STATE_ERROR)resapp-error?app-error:-1;pw_thread_loop_unlock(app-loop);returnres;}等待侧必须使用while循环检查条件而不是被唤醒后直接认为条件已经满足。线程同步中可能出现多次唤醒也可能多个状态共用同一个signal路径。正确做法是signal只负责唤醒条件变量只负责等待真正的业务状态必须由共享状态变量判断。如果调用方需要确认等待线程已经处理过通知可以使用wait_for_accepttrue。staticvoidnotify_and_wait_accept(structapp_data*app){pw_thread_loop_lock(app-loop);app-donetrue;pw_thread_loop_signal(app-loop,true);pw_thread_loop_unlock(app-loop);}等待线程收到signal后处理共享状态并调用pw_thread_loop_accept确认。staticvoidwait_and_accept(structapp_data*app){pw_thread_loop_lock(app-loop);while(!app-done)pw_thread_loop_wait(app-loop);/* * 这里已经观察到done状态可以执行必要处理。 */pw_thread_loop_accept(app-loop);pw_thread_loop_unlock(app-loop);}wait_for_accepttrue适合需要严格同步的路径。调用方发送signal后不会立即继续执行而是等待等待方调用accept。这样可以保证等待方已经观察到共享状态变化。工程上要特别注意三点。第一signal之前要先更新共享状态。否则等待线程可能被唤醒但检查条件时仍然发现状态没有变化。第二等待侧要用while检查条件。不要把signal本身当成业务完成标志。第三不要把pw_thread_loop_signal当作任务投递接口。如果需要让Loop线程执行某个函数应使用适合Loop任务投递的接口而不是只发送条件通知。5.一句话总结pw_thread_loop_signal是PipeWireThread Loop中的线程同步通知接口它唤醒pw_thread_loop_wait等待方必要时通过wait_for_accept和pw_thread_loop_accept形成确认握手但它不负责执行Loop任务也不直接改变PipeWire对象状态。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价