What’s the simplest way to deal with events in C in this situation

cevent-programmingmultithreading

I'm writing a text-based game, in C. I want the game to handle NPCs movement and actions in the background, while the user is making his moves. I'd also use time-based events to tell the user when midnight is (in game-time), or to activate certain things at certain times.

I know that Dwarf Fortress is all single thread stuff, but I can't understand how that's done. I don't know how he handles events. Surely he's not polling.

I've never done any thread programming, or anything with sockets. I've been programming for a while, but I know nothing about those things.

I googled options, but there seems to be a lot of stuff that comes under the heading of event-handling. I have no idea where to start. The first idea that comes to mind, is have two separate programs communicating through a text file, but that seems like a very ugly solution.

What's the simplest solution to handle events such as I described?

I'm currently working in Windows but I would switch over to linux if it's easier. I just happened to be using a Windows machine when I started, so it doesn't matter which.

Best Answer

It is operating system specific (or hardware specific if you are coding some kernel-like software on the bare metal like an OS kernel -see osdev.org-, in freestanding C). Stricto sensu you probably cannot write a game in purely standard hosted C99 (without using any external library, except the C standard library using only the few functions standardized in C99): you need to use some operating system service.

I'm focusing on Linux in my answer below.

If you are coding on Linux (in hosted C, as all user programs are), you'll code your event loop around a multiplexing syscall like poll(2) (or perhaps the older select(2), which I usually don't recommend; see also epoll(7)). Read about the C10K problem. You might use some event loop library like libev or libevent.

If you are unfamiliar with most Linux syscalls (listed in syscalls(2)...), read Advanced Linux Programming.

Reading and polling the terminal is tricky on Linux (because tty-s are quite complex). You probably want to use some library, like ncurses, to make a terminal application.

If you want to code a GUI application, you'll practically use some toolkit framework like Qt or Gtk (or libsdl). They provide an event loop, and you'll need to register callbacks (read also about continuations, it is a relevant concept).

If you want to have two programs (written by you) communicating, you'll need to use some IPC machinery, notably pipe(7)-s. You'll probably need some event loop in some (or both) of them.

For time-related issues, poll(2) (so all event loop libraries built above it) is given a delay. See also time(7).

I don't recommend using signal(7)-s in your case (signals are an interrupt like abstraction provided by the OS, notably POSIX ones). If you do, be very careful, it is tricky. A signal handler is only allowed to call very few async-signal-safe functions, and the usual way is often to simply set some volatile sig_atomic_t flag in it, to be tested and reset inside your event loop. See also POSIX signal concepts chapter.


If you are coding on a non-POSIX operating system like Windows, you need to learn how to write event loops on it, and what is the low-level system API. You'll probably find some library for that. There exist a few libraries (e.g. Qt & POCO - both for and in C++) which are cross-platform. Windows programming is very different from POSIX programming, I know nothing about it.

Related Topic