The use of messages to signal events occurring is a fairly common (if not ubiquitous) practise in the GUI world. In a project I'm working on at the moment, I found that the easiest way to implement what I needed was via a simple message pump, allowing several independent pieces of code to work together without needing special synchronisation, and especially without needing to know the implementation of each other.
I present the implementation I came up with below. I would welcome any feedback regarding improving this (or fixing any oversights on my part). Particularly if anyone wishes to use this I would be very glad to hear and may publish as a library once it is sufficiently stable.
message_pump.h
#include <map>
message_pump.cpp
#include <deque>
#include <map>
#include <memory>
std::deque<Message> messages;
std::map<MSG_TYPE, HANDLER_FUNC> handlers;
void add_message_handler(MSG_TYPE msg_type, HANDLER_FUNC handler)
{
handlers[msg_type] = handler;
}
void add_message(Message *message)
{
messages.push_back(*message);
}
void message_pump()
{
if (messages.size() > 0)
{
std::auto_ptr<Message> message(new Message(messages.front()));
messages.pop_front();
// We handle deleting the message object, but the handler function needs
// to delete anything pointed to by content_ptr
handlers[message->msg_type](message.get());
}
}
Example user code
#include "mbed.h"
#include "TextLCD.h"
#include "message_pump.h"
InterruptIn button(p12);
unsigned int count = 0;
#define PRESSED_BUTTON 100
TextLCD lcd(p23, p24, p25, p26, p27, p28, TextLCD::LCD16x2);
void press_button()
{
Message message;
message.msg_type = PRESSED_BUTTON;
message.value = 50;
message.content_ptr = NULL;
add_message(&message);
}
void handle_button(Message *message)
{
lcd.cls();
lcd.printf("%u", count + message->value);
++count;
}
int main() {
button.rise(&press_button);
add_message_handler(PRESSED_BUTTON, &handle_button);
while (1)
{
message_pump();
}
}
The example code above is a very simple example which add the value1 member of the message to the count variable and displays it on an attached LCD. Upon pressing the button you should see the count begin at 50. This is probably not a very realistic example of use, but I think it serves the purpose of demonstrating the code. One advantage here is that as long as only one thread calls message_pump, the handler functions don't need to be re-entrant.
One outstanding todo item I know about is that the add_message function needs to be made thread safe.
The use of messages to signal events occurring is a fairly common (if not ubiquitous) practise in the GUI world. In a project I'm working on at the moment, I found that the easiest way to implement what I needed was via a simple message pump, allowing several independent pieces of code to work together without needing special synchronisation, and especially without needing to know the implementation of each other.
I present the implementation I came up with below. I would welcome any feedback regarding improving this (or fixing any oversights on my part). Particularly if anyone wishes to use this I would be very glad to hear and may publish as a library once it is sufficiently stable.
message_pump.h
message_pump.cpp
Example user code
The example code above is a very simple example which add the value1 member of the message to the count variable and displays it on an attached LCD. Upon pressing the button you should see the count begin at 50. This is probably not a very realistic example of use, but I think it serves the purpose of demonstrating the code. One advantage here is that as long as only one thread calls message_pump, the handler functions don't need to be re-entrant.
One outstanding todo item I know about is that the add_message function needs to be made thread safe.