Message Queues#
Basic Usage#
Fixed size data items
get()blocks when no items availableput()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