[pulseaudio-discuss] [PATCH v8] pipe-source: implement autosuspend option
Raman Shishniou
rommer at ibuffed.com
Tue Feb 20 21:04:18 UTC 2018
On 02/20/2018 11:04 PM, Georg Chini wrote:
> On 20.02.2018 19:49, Raman Shishniou wrote:
>> On 02/20/2018 07:02 PM, Georg Chini wrote:
>>> On 20.02.2018 16:38, Raman Shyshniou wrote:
>>>> Currently the pipe-source will remain running even if no
>>>> writer is connected and therefore no data is produced.
>>>> This patch adds the autosuspend=<bool> option to prevent this.
>>>> Source will stay suspended if no writer is connected.
>>>> This option is enabled by default.
>>>> ---
>>>> src/modules/module-pipe-source.c | 279 +++++++++++++++++++++++++++++----------
>>>> 1 file changed, 212 insertions(+), 67 deletions(-)
>>>>
>> I think I need post a simple pseudo code of new thread loop because it
>> was completely rewritten. There are too many changes in one patch.
>> It can be difficult to see the whole picture of new main loop.
>
> Well, I applied the patch and looked at the result. I still don't like the approach.
>
> I would propose this:
>
> auto_suspended = false;
> revents = 0
> events = POLLIN
>
> for (;;) {
>
> /* This is the part that is run when the source is opened
> * or auto suspended
> if (SOURCE_IS_OPENED(source) || auto_suspended) {
>
> /* Check if we wake up from user suspend */
> if (corkfd >= 0 && !auto_suspended) {
> len = 0
> close pipe for writing
> }
>
> /* We received POLLIN or POLLHUP or both */
> if (revents) {
>
> /* Read data from pipe */
> len = read data
>
> /* Got data, post it */
> if (len > 0) {
> if (auto_suspend) {
> send unsuspend message
> auto_suspend = false
> }
> post data
>
> /* Got POLLHUP or POLLIN without data, writer disconnected */
> } else if (len = 0) {
> send suspend message
> auto_suspend = true
> }
>
> /* else Handle error */
> else
> handle error
>
> events = POLLIN
> }
>
> /* This is the part that is run, when the source is
> * suspended by user */
> } else {
>
> if (corkfd < 0)
> open pipe for writing
> events = 0
> }
>
> /* This is run always */
> run rtpoll
> ... check errors ...
> }
>
> I think this is more consistent with how the other thread functions are
> written and also has a clearer structure.
>
Ok. I'll try to do something like this.
>>
>> pollfd = NULL;
>> rtpoll_item = NULL;
>> chunk.length = 0; // length of pending data in chunk.memblock
>> chunk.memblock = pa_memblock_new(); // always allocated
>>
>> for (;;) {
>>
>> /**************************************************
>> * run rtpoll
>> */
>> if (chunk.length > 0) {
>> /* we have a pending data */
>> if (rtpoll_item) {
>> /* stop polling pipe
>> * the only way to be here:
>> * source was just suspended */
>> ... free rtpoll_item ...
>> rtpoll_item = NULL;
>> }
>> } else {
>> /* we have no pending data */
>> if (rtpoll_item == NULL) {
>> /* start polling pipe
>> * the only way to be here:
>> * source was just resumed */
>> ... allocate rtpoll_item, get pollfd ...
>> pollfd->events = POLLIN;
>> pollfd->fd = u->fd;
>> }
>> }
>>
>> pa_rtpoll_run()
>>
>> ... check errors ...
>>
>> if (rtpoll_item) {
>> /* we polled pipe */
>> ... refresh pollfd ...
>> } else
>> /* we are waiting for source state changes */
>> pollfd = NULL;
>>
>> /**************************************************
>> * Read data
>> */
>> if (pollfd && pollfd->revents) {
>>
>> ... read data from pipe ...
>>
>> if (len > 0) {
>> chunk.length = len;
>>
>> /* source is autosuspended? */
>> if (u->corkfd >= 0) {
>> ... send resume message ...
>> close(u->corkfd);
>> u->corkfd = -1;
>> }
>> }
>>
>> if (len == 0) {
>> /* sourece not autosuspended? */
>> if (u->corkfd < 0) {
>> ... send suspend message ...
>> u->corkfd = open(pipe, O_WRONLY);
>> }
>> }
>>
>> if (len < 0) {
>> ... check read error ...
>> }
>> }
>>
>> /**************************************************
>> * Post data
>> */
>> if (source is opened) {
>
> After an auto-unsuspend, the result of the above comparison is undefined.
> It may be that the main thread already processed the unsuspend message,
> maybe not.
The above comparison check thread_info.state. This value changed in i/o thread context,
i.e. during pa_rtpoll_run(). It will be PA_SOURCE_SUSPENDED right after we send a message
and becomes PA_SOURCE_RUNNING / PA_SOURCE_IDLE after one or two next poll runs.
>
>> ... post data ...
>> unref(chunk.memblock);
>> chunk.memblock = pa_memblock_new();
>> chunk.length = 0;
>> }
>>
>> /* chunk.length can be greater than 0 only if we are suspended right now
>> * we need to stop polling pipe and wait while state will be changed to RUNNING or IDLE
>> * to post pending data */
>
> If we are user suspended right now, the data should never be posted. Data that is read
> while we are user-suspended should be discarded. Data that arrives while we are
> auto-suspended should be posted.
>
>
>> }
>>
>> I can convert all changes to patch series if you want.
>>
--
Raman
More information about the pulseaudio-discuss
mailing list