[vlc-devel] [PATCH 1/7] playlist/background_worker: introduce background-worker utility
Rémi Denis-Courmont
remi at remlab.net
Wed Mar 22 18:56:02 CET 2017
Le keskiviikkona 22. maaliskuuta 2017, 18.43.44 EET Filip Roséen a écrit :
> > I think you should not keep reproducing the same.
>
> Where would you recommend putting them? I was struggling to find a
> good place, but I guess `src/misc` is good enough?
I don´t particularly like src/misc either, but that still seems saner than
src/playlist/
(...)
> > I don´t see the point in doing that there. You have all the disadvantage
> > of
> > insulated private data, and none of the advantages, since the private data
> > is still exposed to the owner.
>
> The reason there is a *data-member* of type `struct
> background_worker_private` was because, inspired by some recent
> changes by you (which I really like), I wanted
> `background_worker_Init` to be always successful (in order to prevent
> the number of error-paths).
I would just inline the private structure into the public one. Or rather, I
would design the thing so that there are no public members at all.
You can still use init/deinit instead of new/delete if you want. Only expose
the structure layout is exposed for the purpose of allocation/storage.
> It can of course be moved to be *translation-unit* local to
> `src/playlist/misc/background_worker.c`.
> > > +
> > > + vlc_mutex_lock( &priv->lock );
> > > + for( ;; )
> > > + {
> > > + vlc_cond_broadcast( &priv->wait );
> > > +
> > > + if( priv->current.handle == NULL )
> > > + {
> > > + if( vlc_array_count( &priv->queue ) == 0 )
> > > + break;
> > > +
> > > + struct background_worker_item* item =
> > > + vlc_array_item_at_index( &priv->queue, 0 );
> > > +
> > > + void* handle;
> > > + if( !worker->pf_start( priv->owner, item->entity, &handle )
> > > )
> > > + {
> > > + priv->current.item = item;
> > > + priv->current.handle = handle;
> > > + priv->current.deadline = item->timeout > VLC_TS_INVALID
> > > + ? mdate() + item->timeout : INT64_MAX;
> > > + }
> > > +
> > > + vlc_array_remove( &priv->queue, 0 );
> > > + continue;
> > > + }
> > > +
> > > + for( ;; )
> > > + {
> > > + bool const b_timeout = priv->current.deadline < mdate();
> > > +
> > > + vlc_mutex_unlock( &priv->lock );
> > > +
> > > + if( b_timeout ||
> > > + worker->pf_probe( priv->owner, priv->current.handle ) )
> > > + {
> > > + worker->pf_stop( priv->owner, priv->current.handle );
> > > + worker->pf_release( priv->current.item->entity );
> > > +
> > > + vlc_mutex_lock( &priv->lock );
> > > + break;
> > > + }
> > > +
> > > + vlc_mutex_lock( &priv->lock );
> > > + vlc_cond_timedwait( &priv->wait, &priv->lock,
> > > + priv->current.deadline );
> >
> > This sequence of two instructions can´t be correct, AFAIK.
>
> `(1)`
>
> Oh that was an unfortunate side-effect of some heavy rebasing right
> before pushing to *vlc-devel*, the signal can of course be lost if the
> background-task finishes during the time the lock is released.
>
> I will fix this in an upcoming patch, thank you!
>
> > > + }
> > > +
> > > + priv->current.item = NULL;
> > > + priv->current.handle = NULL;
> > > + }
> > > +
> > > + priv->active = false;
> > > + vlc_mutex_unlock( &priv->lock );
> > > + return NULL;
> > > +}
> > > +
> > > +static void BackgroundWorkerCancel( struct background_worker* worker,
> > > void* id) +{
> > > + struct background_worker_private* priv = &worker->p;
> > > +
> > > + vlc_mutex_lock( &priv->lock );
> > > + for( size_t i = 0; i < vlc_array_count( &priv->queue ); )
> > > + {
> > > + struct background_worker_item* item =
> > > + vlc_array_item_at_index( &priv->queue, i );
> > > +
> > > + if( id == NULL || item->id == id )
> > > + {
> > > + vlc_array_remove( &priv->queue, i );
> >
> > Looks like reinventing vlc_array_index_of_item().
>
> I was tempted to introduce an alternative to `vlc_array_index_of_item`
> that would take a callback so that one could query something other
> than the item-address itself (but have the same semantics as
> `vlc_array_index_of_item`).
> It would simplify the code, but I did not find too many occurances
> where such a new function would benefit the codebase as a whole, and
> as it wouldn't be used too many times in `background_worker.c`, I was
> hesitant to add a *translation-unit* local helper.
>
> > > + worker->pf_release( item->entity );
> >
> > This seems to assume that the callbacks are reentrant. It might be true.
> > But it seems like a dangerous design assumption.
>
> A `pf_release` callback that would release the worker in which the
> item is part of would be the only case where we would end up in a
> reentrent state, and as I thought that did not make sense I didn't go
> out to make that a valid usecase.
Sorry, I am not sure what you are trying to express here.
My point is that pf_release is also used in function calls, and without the
lock. So it has to be reentrant as things stand. And I´m not sure that´s a
good idea. At the very least, this would need to be clearly and explicitly
documented.
--
雷米‧德尼-库尔蒙
https://www.remlab.net/
More information about the vlc-devel
mailing list