[pulseaudio-discuss] Allowing anonymous structs and unions
Ahmed S. Darwish
darwish.07 at gmail.com
Wed Sep 23 01:34:06 PDT 2015
Hi everyone,
On Wed, Sep 23, 2015 at 02:27:55AM -0400, Alexander E. Patrakov wrote:
> On 09/23/2015 02:12 AM, Tanu Kaskinen wrote:
> >Hi all,
> >
> >We haven't been using anonymous structs and unions so far, because
> >they've been non-standard in the past. C11 added support for them,
> >however. GCC has supported them longer than that, I don't know about
> >other compilers. Anonymous structs and unions are nice, and I think we
> >should start allowing them. Any objections?
>
> I think it would be a good idea to send one small example patch that makes a
> use of them, just to demonstrate where exactly in PulseAudio they would make
> the code more elegant.
>
Sure, this pattern is used heavily in the memfd patches :-)
### Anonymous unions
Used to provide the mempool with polymorphic memory region access
regardless of the type of memory used:
union {
pa_mem mem;
union {
pa_shm shm;
pa_memfd memfd;
pa_privatemem privatemem;
} per_type;
};
This way, a lot of the mempools code can transparently access its
backend memory by using `mempool->mem.ptr' and `mempool->mem.size`.
This also saves us from polluting the mempool memblock.c code with
a huge number of switch cases ;-)
### Anonymous structs
They are also used in the memfd patches, but they're really used
to minimize code repetitions and make relationships explicit.
Basically, we want to build an inheritance relationship: pa_shm,
pa_memfd, and pa_privatemem has the common parent pa_mem. We also
want to make this relationship explicit since it's at the core of
the anonymous polymorphic union mentioned above.
To do so without introducing extra (compile-time) dereferences,
the following patten is used:
/* Parent anonymous structure representing a plain memory
* area and its size. Different structures inherit from this,
* representing different memory area types (e.g. Posix SHM,
* Linux memfds, or private mallocs).
*
* To inherit from this object, just include PA_MEM_STRUCT as
* the very first element of your structure definition. */
#define PA_MEM_STRUCT struct { \
void *ptr; \
size_t size; \
} PA_GCC_PACKED
typedef struct pa_mem {
PA_MEM_STRUCT;
} pa_mem;
This way, children pa_shm, pa_memfd, and pa_privatemem can be
defined as follows:
typedef struct pa_shm {
PA_MEM_STRUCT;
unsigned id;
bool do_unlink;
} pa_shm;
typedef struct pa_memfd {
PA_MEM_STRUCT;
int fd;
} pa_memfd;
typedef struct pa_privatemem {
PA_MEM_STRUCT;
} pa_privatemem;
..
So to summarize, such annotation explicitly shows the inheritance
relationship, minimize code repeition in the struct defintions, and
also saves us an extra compile-time dereference in shm.c, memfd.c,
and privatemem.c code. It also really works in tandem with the
earlier polymorphic union:
union {
pa_mem mem;
union {
pa_shm shm;
pa_memfd memfd;
pa_privatemem privatemem;
} per_type;
};
Hopefully these patterns will be OK from your side :-)
Regards,
--
Darwish
http://darwish.chasingpointers.com
More information about the pulseaudio-discuss
mailing list