Of Humble Constructs: The Event Loop
Software development is like a 3d-jig saw puzzle. Small "pieces" - in the form of basic instructions - are used to construct larger pieces of increasing complexity, such as sub routines, functions, and objects. At differing levels of abstraction this can be anything from combining basic arithmetical operations with a stack to create a RPN calculator, all the way up to the networking libraries, multi threading, and advanced data structures needed to create something such as a web server. Despite the difference in complexity of the two, both tasks are accomplished by combining constructs to create something bigger than the sum of its pieces.
In todays post I'm going to discuss one such construct that is found in all corners of software development from game programming, to web servers, to programming REPL environments: The event loop. This construct is so pervasive, that it lies at the base of an entire paradigm of programming - event driven programming.
What Is an Event Loop, Anyway?
An event loop is exactly what it sounds like: A loop used to process events. In order for programs to be interactive and respond to such things as user input, or receiving a message over a network, an application needs a way of monitoring for and responding to these events. This is the job of the event loop.
In a webserver for example, an event loop is used to listen for incoming connections, and when one is detected, forks a thread to accept and handle the new connection, while the connection event loop goes back to listening for incoming connections - ad infinitum. Meanwhile, the new thread uses a different event loop to receive requests from clients, and send the requested data back to them during the users session.
There are many, many, MANY different uses cases for event loops, and based on the type of events being processed, they generally fall into one of two categories: Blocking or Non Blocking Event Loops.
Blocking Vs Non-Blocking
There are two main types of event loops: blocking and non-block. Of the two, the simplest type of event loop is blocking. Blocking Event Loops are named as such because they inhibit further execution of the program while waiting for an event. Non-blocking loops on the other hand check if there is any input to be processed, and if not, continues executing the loop body.
The Read-Eval-Print-Loop that you encounter with various interpreted languages like Lisp and Python are examples of blocking event loops: until you input an expression or statement for the REPL to evaluate and press enter, it will happily sit there doing nothing.
Non-blocking event loops are used in video games to give the appearance of "the world happening around you" - if a first person shooter only proceeded once the user provided the input, and then stopped to wait for more input, it would be a very strange game indeed.
Blocking Event Loops
For use in the REPL of a programming environment, a blocking event loop not only makes perfect sense - it's desirable! The following pseudocode highlights how the action of waiting on input causes blocking. Until there is input to process, the loop cant proceed, and once it does process some input, and do what ever other tasks may need to be done, it loops to arrive back at waiting for the input.
void blockingEventLoop() {
while (true) {
string input = getSomeInput(); // THIS LINE CAUSES BLOCKING
if (input.meetsCriteria()) {
performActionFromInput(input);
}
doSomeStuff();
etcEtcEtc();
}
}
Something like a webserver however requires the use of non-blocking event loops: having the entire application stop everything and wait for an event that may or may not happen in a timely manner - if at all - would be completely unacceptable.
Non-blocking Event Loops
void event_loop() {
while (true) {
if (eventQueue.isEmpty() == false) {
processIncoming(eventQueue.pop());
}
doSomething();
thenTheOtherThing();
etcEtcEtc();
}
}
Non-blocking event loops work thanks to a technique called polling. Input is held in a buffer - often a queue, and at each iteration the event loop polls the input queue which is a fancy way of saying it checks if there is any input on the queue to process, and if not, will perform what ever other tasks take place in the loop, only stopping to process input when there is actually input to process.
No matter what kind of applications you like to develop, at some point you will implement an event loop, and now at least when you do, you know you have options. Until next time, Happy Hacking!
-
Pratt Parsing: Top-Down Operator Precedence
-
Generating P-Code by AST Traversal
-
Ternary Search Tries: String Specific Ordered Symbol Tables
-
Digital Search Trees
-
Lossless Compression Part III: Huffman Coding
-
Lossless Compression Part II: The LZ77 Algorithm
-
Lossless Compression Part I: Working with Bits in a Byte Oriented World
-
Bottom Up AVL Tree: The OG Self-Balancing Binary Search Tree
-
A Different Take on Merge Sort: Binary Search Trees?
-
Deleting Entries From Open-Address Hash tables
Leave A Comment