[pulseaudio-discuss] Few questions about PA API

David Henningsson david.henningsson at canonical.com
Tue Jun 10 03:19:36 PDT 2014


Thanks for the patch. Overall I think this is good new functionality.

Here's a review, which is mostly about details:

On 2014-04-15 02:14, Lukasz Marek wrote:
>
>  From ab9e95ab62602ed107b5d46642149de7ead15c10 Mon Sep 17 00:00:00 2001
> From: Lukasz Marek<lukasz.m.luki2 at gmail.com>
> Date: Tue, 15 Apr 2014 02:08:23 +0200
> Subject: [PATCH] Add pa_stream_write_ext_free() function.

Missing prefix, maybe "Client API:" would be good here, so the subject 
becomes:
"Client API: Add Add pa_stream_write_ext_free function"


> New function allows to pass data pointer that is a member
> of the outer structure that need to be freed too when data
> is not needed anymore.
>
> Signed-off-by: Lukasz Marek<lukasz.m.luki2 at gmail.com>
> ---
>   src/map-file             |  1 +
>   src/pulse/stream.c       | 20 ++++++++++++++++----
>   src/pulse/stream.h       | 11 +++++++++++
>   src/pulsecore/memblock.c | 14 ++++++++++++--
>   src/pulsecore/memblock.h |  2 +-
>   5 files changed, 41 insertions(+), 7 deletions(-)
>
> diff --git a/src/map-file b/src/map-file
> index dc36fdc..5159829 100644
> --- a/src/map-file
> +++ b/src/map-file
> @@ -330,6 +330,7 @@ pa_stream_update_sample_rate;
>   pa_stream_update_timing_info;
>   pa_stream_writable_size;
>   pa_stream_write;
> +pa_stream_write_ext_free;
>   pa_strerror;
>   pa_sw_cvolume_divide;
>   pa_sw_cvolume_divide_scalar;
> diff --git a/src/pulse/stream.c b/src/pulse/stream.c
> index 8e35c29..2c9a777 100644
> --- a/src/pulse/stream.c
> +++ b/src/pulse/stream.c
> @@ -1464,13 +1464,14 @@ int pa_stream_cancel_write(
>       return 0;
>   }
>
> -int pa_stream_write(
> +int pa_stream_write_ext_free(
>           pa_stream *s,
>           const void *data,
>           size_t length,
>           pa_free_cb_t free_cb,
>           int64_t offset,
> -        pa_seek_mode_t seek) {
> +        pa_seek_mode_t seek,
> +        const void *free_cb_data) {

I think it would be wise to switch order here, i e, to have the free_cb 
just before free_cb_data.

Also, because "userdata" usually is "void *" (not "const void *"), maybe 
it would make more sense to have free_cb_data as "void *" too?

>
>       pa_assert(s);
>       pa_assert(PA_REFCNT_VALUE(s) >= 1);
> @@ -1519,7 +1520,7 @@ int pa_stream_write(
>               chunk.index = 0;
>
>               if (free_cb && !pa_pstream_get_shm(s->context->pstream)) {
> -                chunk.memblock = pa_memblock_new_user(s->context->mempool, (void*) t_data, t_length, free_cb, 1);
> +                chunk.memblock = pa_memblock_new_user(s->context->mempool, (void*) t_data, t_length, free_cb, 1, (void*) free_cb_data);
>                   chunk.length = t_length;
>               } else {
>                   void *d;
> @@ -1544,7 +1545,7 @@ int pa_stream_write(
>           }
>
>           if (free_cb && pa_pstream_get_shm(s->context->pstream))
> -            free_cb((void*) data);
> +            free_cb((void*) free_cb_data);
>       }
>
>       /* This is obviously wrong since we ignore the seeking index . But
> @@ -1591,6 +1592,17 @@ int pa_stream_write(
>       return 0;
>   }
>
> +int pa_stream_write(
> +        pa_stream *s,
> +        const void *data,
> +        size_t length,
> +        pa_free_cb_t free_cb,
> +        int64_t offset,
> +        pa_seek_mode_t seek) {
> +
> +    return pa_stream_write_ext_free(s, data, length, free_cb, offset, seek, data);
> +}
> +
>   int pa_stream_peek(pa_stream *s, const void **data, size_t *length) {
>       pa_assert(s);
>       pa_assert(PA_REFCNT_VALUE(s) >= 1);
> diff --git a/src/pulse/stream.h b/src/pulse/stream.h
> index 7ceb569..6fbd663 100644
> --- a/src/pulse/stream.h
> +++ b/src/pulse/stream.h
> @@ -554,6 +554,17 @@ int pa_stream_write(
>           int64_t offset,          /**< Offset for seeking, must be 0 for upload streams */
>           pa_seek_mode_t seek      /**< Seek mode, must be PA_SEEK_RELATIVE for upload streams */);
>
> +/** Function does exactly the same as pa_stream_write() with the difference
> + *  that free_cb_data is passed to free_cb instead of data. \since 6.0 */
> +int pa_stream_write_ext_free(
> +        pa_stream *p             /**< The stream to use */,
> +        const void *data         /**< The data to write */,
> +        size_t nbytes            /**< The length of the data to write in bytes */,
> +        pa_free_cb_t free_cb     /**< A cleanup routine for the data or NULL to request an internal copy */,
> +        int64_t offset,          /**< Offset for seeking, must be 0 for upload streams */

Nitpick: Inconsistent comma placement. I saw it was there in 
pa_stream_write too, but let's fix it anyway :-)

> +        pa_seek_mode_t seek      /**< Seek mode, must be PA_SEEK_RELATIVE for upload streams */,
> +        const void *free_cb_data /**< Argument passed to free_cb function */);
> +
>   /** Read the next fragment from the buffer (for recording streams).
>    * If there is data at the current read index, \a data will point to
>    * the actual data and \a nbytes will contain the size of the data in
> diff --git a/src/pulsecore/memblock.c b/src/pulsecore/memblock.c
> index 9cc02c1..3d75d99 100644
> --- a/src/pulsecore/memblock.c
> +++ b/src/pulsecore/memblock.c
> @@ -83,6 +83,8 @@ struct pa_memblock {
>           struct {
>               /* If type == PA_MEMBLOCK_USER this points to a function for freeing this memory block */
>               pa_free_cb_t free_cb;
> +            /* If type == PA_MEMBLOCK_USER this is passed as free_cb argument */
> +            pa_atomic_ptr_t free_cb_data;

Hmm, I'm not sure why free_cb_data needs to be atomic. If it's only set 
once in the creation of the memblock, then why not keep it as "void *" 
consistently?

>           } user;
>
>           struct {
> @@ -387,7 +389,13 @@ pa_memblock *pa_memblock_new_fixed(pa_mempool *p, void *d, size_t length, bool r
>   }
>
>   /* No lock necessary */
> -pa_memblock *pa_memblock_new_user(pa_mempool *p, void *d, size_t length, pa_free_cb_t free_cb, bool read_only) {
> +pa_memblock *pa_memblock_new_user(
> +        pa_mempool *p,
> +        void *d,
> +        size_t length,
> +        pa_free_cb_t free_cb,
> +        bool read_only,

Same as previous comment; keep free_cb next to free_cb_data

> +        void *free_cb_data) {
>       pa_memblock *b;
>
>       pa_assert(p);
> @@ -410,6 +418,7 @@ pa_memblock *pa_memblock_new_user(pa_mempool *p, void *d, size_t length, pa_free
>       pa_atomic_store(&b->please_signal, 0);
>
>       b->per_type.user.free_cb = free_cb;
> +    pa_atomic_ptr_store(&b->per_type.user.free_cb_data, free_cb_data);
>
>       stat_add(b);
>       return b;
> @@ -513,7 +522,7 @@ static void memblock_free(pa_memblock *b) {
>       switch (b->type) {
>           case PA_MEMBLOCK_USER :
>               pa_assert(b->per_type.user.free_cb);
> -            b->per_type.user.free_cb(pa_atomic_ptr_load(&b->data));
> +            b->per_type.user.free_cb(pa_atomic_ptr_load(&b->per_type.user.free_cb_data));
>
>               /* Fall through */
>
> @@ -647,6 +656,7 @@ static void memblock_make_local(pa_memblock *b) {
>       /* Humm, not enough space in the pool, so lets allocate the memory with malloc() */
>       b->per_type.user.free_cb = pa_xfree;
>       pa_atomic_ptr_store(&b->data, pa_xmemdup(pa_atomic_ptr_load(&b->data), b->length));
> +    pa_atomic_ptr_store(&b->per_type.user.free_cb_data, pa_atomic_ptr_load(&b->data));
>
>       b->type = PA_MEMBLOCK_USER;
>       b->read_only = false;
> diff --git a/src/pulsecore/memblock.h b/src/pulsecore/memblock.h
> index 502f207..0bfdc92 100644
> --- a/src/pulsecore/memblock.h
> +++ b/src/pulsecore/memblock.h
> @@ -85,7 +85,7 @@ pa_memblock *pa_memblock_new(pa_mempool *, size_t length);
>   pa_memblock *pa_memblock_new_pool(pa_mempool *, size_t length);
>
>   /* Allocate a new memory block of type PA_MEMBLOCK_USER */
> -pa_memblock *pa_memblock_new_user(pa_mempool *, void *data, size_t length, pa_free_cb_t free_cb, bool read_only);
> +pa_memblock *pa_memblock_new_user(pa_mempool *, void *data, size_t length, pa_free_cb_t free_cb, bool read_only, void *free_cb_data);
>
>   /* A special case of pa_memblock_new_user: take a memory buffer previously allocated with pa_xmalloc()  */
>   #define pa_memblock_new_malloced(p,data,length) pa_memblock_new_user(p, data, length, pa_xfree, 0)

-- 
David Henningsson, Canonical Ltd.
https://launchpad.net/~diwic


More information about the pulseaudio-discuss mailing list