Skip to content
This repository has been archived by the owner on Nov 12, 2023. It is now read-only.

[E] Engine multithreading model

Madman10K edited this page Aug 10, 2023 · 2 revisions

Our game engine uses a very limited multithreading model. In general we have 4 types of threads:

  1. Audio threads
  2. Video threads - For buffering cutscenes
  3. Render threads
  4. Logic threads

You can already guess what thread does what, in the following section we will explain how we sync them and how each relates to each other

Logic threads

Logic threads are threads created using the worker API. When the engine launches we fetch how many threads your system has, we allocate the renderer thread and a single audio thread to serve as our manager. Additionally a single logic thread is created for your game state class if it's provided to the game mode.

Generally think of logic threads as disposable general threads where the game developer sets their purpose.

A logic thread is created by passing the create function of the thread interface a callback function. The first responsibility of the threading manager is to determine how to handle the function. Since we already know how many threads our system has and how much are in use the logic thread manager needs to figure out how to schedule jobs cleanly as to not create any threading overhead.

In case the currently created threads on the system are less than the max number of threads, a new thread will be created or an orphaned thread will be taken over. Orphaned threads are threads that have been inactive and have been taken over by the threading manager. When the game developer marks a logic thread as inactive, we make it orphaned and wait for a countdown specified by the developer to hit 0. If no thread has been created while the countdown hit 0 the thread gets removed, if a new thread is created when the countdown is not 0 then we take over the old thread.

In case we run out of available threads, we append the callback to the event list of the threads. This way we balance loads along logic threads and preserve performance by not creating more threads than the CPU has available.

Logic threads run completely independently of the render thread. Because of this we recommend exchanging data with your scripting class after your thread finishes work. This way you can synchronize data and present it when it's needed either in the current or next frame

More information coming soon!