I'm writing an embedded control system in C that consists of multiple tasks that send messages to each other (a fairly common idiom, I believe!), but I'm having a hard time designing a mechanism which:
- is neat
- is generic
- is relatively efficient
- most importantly: is platform independent (specifically, doesn't violate strict-aliasing or alignment issues)
Conceptually, I'd like to represent each message type as a separate struct definition, and I'd like a system with the following functions (simplified):
void sendMsg(queue_t *pQueue, void *pMsg, size_t size);
void *dequeueMsg(queue_t *pQueue);
where a queue_t comprises a linked list of nodes, each with a char buf[MAX_SIZE] field. The system I'm on doesn't have a malloc() implementation, so there'll need to be a global pool of free nodes, and then one of the following (perceived issues in bold):
sendMsg()does amemcpyof the incoming message into the buffer of a free node.
My understanding is that this will have alignment issues unless the caller ofdequeueMsg()does a furthermemcpyon the return value.- or there'll be a
void *getFreeBuffer()function which returns thebuf[]of the next free node, which the caller (the sender) will cast to the appropriate pointer-to-type.
My understanding is that this will now have alignment issues on the way in, and still requires amemcpyafterdequeueMsg()to avoid alignment issues on the way out. - or redefine the buffer in
queue_tnodes as (e.g.)uint32_t buf[MAX_SIZE].
My understanding is that this violates strict aliasing, and isn't platform-independent.
The only other option I can see is to create a union of all the message types along with char buf[MAX_SIZE], but I don't count this as "neat"!
So my question is, how does one do this properly?