Re: Thread safe event loop
For anyone interested, this is what I ran off. Note that it uses an
__asm__ block...
Any comments welcome. This shouldn't be considered "robust".
--Jonathan
[code]
// header-ish stuff
enum event_type { // Types of messages that can be sent. Examples
only.
IGNORE, PLAY, STOP, DIE };
struct Message { // Structure containing the message
// Data
event_type event; // what kind of event is this?
Message * next; // Next event in the queue
// Constructor for convenience
Message(event_type e = IGNORE) : event(e), next(0) {};
};
class MessageQueue { // Event queue with some primitive "mutex" built
in
public:
MessageQueue() : mutex(0), root(0) {};
void Post(event_type);
bool Get(Message&); // Could implement as operator= prolly
private:
void lock() { // mutex lock
unsigned long i = 0;
do {
__asm__ ( // NOTE: X86_64. Non-portable
"lock bts $0, %1; sbbq %%rax, %%rax;"
: "=a"(i) : "m"(mutex));
} while (i != 0 && waitsome());
}
void unlock() { mutex = 0; }
bool waitsome() { // Dummy sleep function. Fill it in.
return true; // must return true
};
unsigned long mutex; // 0 is unlocked, anything else is locked
Message * root; // Message queue
};
// Add a message to the queue of type "event".
void MessageQueue::Post(event_type event) {
Message *m = new Message(event); // Create the message
lock();
if (root) { // Add the message to the end of the queue
Message *q, *p = root;
while (q = p->next) // find the end
p = q;
p->next = m;
} else root = m; // There is no queue, add our message to the
beginning
unlock();
}
// Check for a message in the queue. Non-blocking. Returns true if
there is
// (a message) and copies it to m. Returns false otherwise (and leaves
m alone)
bool MessageQueue::Get(Message& m) {
bool was_an_event = false;
lock();
if (root) { // There's a message in the queue
Message *n = root->next;
m = *root; // Copy the message to the user
delete root; // remove the message from the queue
root = n;
was_an_event = true;
}
unlock();
return was_an_event;
}
// main.cpp
#include <cstdio>
MessageQueue m;
Message what_to_do;
int main(void) {
m.Post(DIE);
while (m.Get(what_to_do)) { // Enter the "event loop"
switch(what_to_do.event) {
case PLAY: printf("I can has play music?\n"); break;
case STOP: printf("Boo. No music.\n"); break;
default: printf("WTF\n");
}
}
return 0;
}
[/code]