Sharing (externing) mempool and queue across different threads in different files (translational units) - failing free

Hi All,

How are you going about sharing queues between different threads in different files?

For example, if I have a thread in:

producer.cpp

// Instantiate pool and queue
MemoryPool<sensor_snapshot_t, 4> sensor_snapshot_mempool;
Queue<sensor_snapshot_t, 4> sensor_snapshot_queue;

... do some stuff ...

// Allocate and send message
sensor_snapshot_t *snap = sensor_snapshot_mempool.try_alloc();
sensor_snapshot_queue.try_put(snap);

And another thread in:

consumer.cpp

// Extern existing pool and queue
extern MemoryPool<sensor_snapshot_t, 4> sensor_snapshot_mempool;
extern Queue<sensor_snapshot_t, 4> sensor_snapshot_queue;

// Retrieve message (this works)
sensor_snapshot_t *sensor_snapshot = NULL;
sensor_snapshot_queue.try_get(&sensor_snapshot);

... do some stuff... 

// Now free (this fails)
status = sensor_snapshot_mempool.free(sensor_snapshot);

I’m able to receive the message with the proper data in the snapshot struct, but it seems unable to free the data in the mempool. After a few messages, the try_alloc() starts returning null even though the queue messages have been consumed (verified via debug).

Is there something obviously incorrect above? I’m running OS 6.1.0

Note: I have tried using .get as opposed to .try_get and the compiler warns me that the former is deprecated - and I receive no data in the consumer task using the deprecated method.

Thank you!

Update - I have solved this locally. The solution above does perform correctly, and the issue was caused by an unrelated factor.

Happy to discuss sharing these resources as a broader topic (to extern, or not to extern) if anyone is interested!

Using the separation of concerns principle, I would put the extern declarations for the queue and memory pool in their own header (e.g. Resource.h) and the variable definitions in their own cpp file (e.g. Resource.cpp). Both the consumer translation unit and the producer translation unit then only have to include Resource.h

1 Like

Hi Breda,

Thanks, that’s exactly how I have it arranged in my final source. I wanted to simplify the question down to basic elements in order to address the after effects of externing the template (i.e. it no longer functioned) - and whether externing these templates in mbed was a common practice (freeRTOS uses a system-managed event loop that functions nicely using event registration, not requiring externs or similar).

Initially my queue was not functioning because the mbed-os official examples show deprecated code for release 6.15:

        osEvent evt = queue.get();
        if (evt.status == osEventMessage) {
            message_t *message = (message_t *)evt.value.p;

^ The above does not work when the templates are externed (and may not work in a non-externed case, I haven’t tried due to deprecation).

Hopefully these examples see some updates soon - they generate compiler warnings.

After switching to the try_-based methods, I fixed an additional issue and the externed queue began functioning.

Thanks for the response!