Message Queues#

Basic Usage#

  • Fixed size data items

  • get() blocks when no items available

  • put() blocks when full

  • _nowait() variants

#include <why-thread.h>
#include <why-messagequeue.h>
#include <why-time.h>
#include <print>

int main()
{
    Why::init();

    auto queue = Why::MessageQueue<int>::create();

    auto producer = Why::Thread::create(
        [&queue](){
            for (int i=0;;i++) {
                Why::msleep(500);
                queue->put(i);
            }
        }
    );
    if (! producer) {
        std::println(stderr, "thread creation failed: {}", producer.error().msg());
        return 1;
    }

    // main thread consumes at highest priority
    while (true) {
        auto elem = queue->get();
        std::println("received {}", *elem);
    }
    return 0;
}

Communicating From An ISR Into Thread Context#

  • Common pattern: in the ISR, quickly transfer work into an easier - schedulable - context

  • Producer is an ISR: cannot wait ⟶ put_noblock()

  • Consumer is a thread: can wait ⟶ get()

  • Main: not a busy loop anymore

  • OS does powermanagement when nothing else happens

#include <why-irq.h>
#include <why-messagequeue.h>
#include <why-time.h>
#include <why-sensor.h>
#include <print>
#include <list>
#include <cstdlib>

using sensor_data = std::pair<uint64_t/*timestamp*/, uint64_t/*value*/>;
auto the_queue = Why::MessageQueue<sensor_data>::create();

int main()
{
    Why::init();

    Why::RandomSensor sensor(0, 100);
    auto isr = [&sensor](int irqnum){
        auto written = the_queue->put_noblock({Why::now_monotonic(), sensor.get_value()});
        if (! written) {
            if (written.error().sys_errno() == EAGAIN)
                std::println(stderr, "OIDA! ZAH AUN!!");
            else {
                std::println(stderr, "OS Error: {}", written.error().msg());
                exit(1);
            }
        }
    };

    Why::IRQ::connect(2, isr);

    while (true) {
        auto sample = the_queue->get();     // <-- wait
        auto [timestamp, value] = *sample;
        std::println("timestamp={}, value={}", timestamp, value);
    }        
    return 0;
}
$ while true; do echo irq 2; done | \
    why-shell code/why-mq-sensor-messagequeue