wspurgin
wspurgin

Reputation: 2733

Implementations for event loop in C/C++ that's nice on the call stack

TL;DR

What is the best implementation for an event loop in C/C++ that manages the call stack well?

Event Loops, the Problem

They're an easy concept: Wait for an event, handle event, wait for more events.

I was looking back over some old projects and came across a simple (and kinda poor) implementation of a search engine, and my curiosity was sparked about the proper way to do event loops.

At the time I'd done something like this (very) simplified example:

int wait_for_query();
int handle_query();

int main(int argc, const char** argv) {
  return wait_for_query();
}

int wait_for_query() {
  // Do some stuff
  return handle_query();
}

int handle_query() {
  // Handle it
  // if query is quit, return quit();
  return wait_for_query();
}

int quit() {
  return 0;
}

This implementation relies on call-chaining to achieve an "event loop". I use quotes because while it's logically an event loop, the call stack continually increases and never unwinds:

                                            wait_for_query____...
                                           /
                       handle_query_______/
                      /
wait_for_query_______/

While it works, it's always adding new stack frames onto the stack and eventually, after enough events, it will cause a Stack Overflow error! (haha so meta).

What I want is something like this:

                       handle_query           handle_query
                      /            \         /            \
wait_for_query_______/              \_______/              \_____...

What I've got so far

I've always heard that an OS is just a while(true) loop that gets interrupted, so (since my OS hasn't gotten a SO error recently) here's what I thought would be good:

But does this actually make it more stack efficient? To my knowledge, while loops (and loops in general) still produce stack frames in assembly language (since they're all branches in execution with scope/local variables/etc.)

What is the best implementation for an event loop in C/C++ that manages the call stack well?

Notes

This question assumes a single threaded event loop. Parallelized answers are acceptable too, but I thought that'd would be a bit much to ask about all at once ;)

Fire away

Upvotes: 4

Views: 7800

Answers (2)

user1129665
user1129665

Reputation:

The initial solutions is fundamentally broken. Event loop looks something like this:

while (q != QUITE) {
  q = wait_for_query();
  handle_query(q);
}

It's as simple as this. Which actually agrees with what you described:

They're an easy concept: Wait for an event, handle event, wait for more events.

In initial code, semantically, handling the event, handle_query(), will never be completed until all future events are also completed, recursively, meaning no event will ever be completed. Which is not what you want.

The detailed might get very complicated, e.g how you get the events? does it blocks or not? how events are dispatched? ... etc.

Upvotes: 4

pevasquez
pevasquez

Reputation: 862

Actually, while won't generate any new stack frames by itself. Stack frames get created when a call instruction is issued.

If you make handle_query return 1 as you mention, then your loop won't grow the stack further than two levels (wait_query+handle_query) for each event it processes:

                                  handle_query           handle_query
                                 /            \         /            \
           wait_for_query_______/              \_______/              \_____...
          /
         /
main_loop

Which looks like the stack structure you were looking for.

Upvotes: 1

Related Questions