Jump to content
  • Advertisement
Sign in to follow this  
  • entry
    1
  • comments
    0
  • views
    1651

Entries in this blog

 

async loading and syncing threads with your mainloop in C++11

Loading resources or map data asynchronously in games is not an easy task. C++11 makes all of this a lot easier. I am going to demonstrate how to create a thread using async. And then how to sync back to the main loop using lambda functions.

Consider the following code, that is blocking:
void onNewGame(){ // Load the map loadMap("level1-1.map"); // Start the game startGame();}void loadMap(const std::string& in_filename){ // ... Do extensive work, freezes the screen for couple seconds.}Lets start by adding the loading code into a thread. Using std::async.
#include // This is the include for asyncvoid onNewGame(){ // Load the map, asynchronously std::async(loadMap, "level1-1.map"); // return and continue normal execution... render your animated loading screen on your mainloop}void loadMap(const std::string& in_filename){ // ... Do extensive work}That was easy?
Now we need to notify the game when the loading is complete. By calling "startGame()" in our example above. This is not as easy as it sound, because the loadMap() function is now running on a different thread. You could set an atomic boolean, and check it every frame. But then we will end up with specific cases all over the place.

What we want is to synchronize with our main loop. Consider the following typical mainloop:
void mainLoop(){ while (true) { game.update(); game.draw(); }}If we were to set a global atomic bool, we would probably put it like this:
void mainLoop(){ while (true) { if (mapLoadingDone) { startGame(); mapLoadingDone = false; } game.update(); game.draw(); }}And mapLoadingDone is a boolean that would be set to true at the end of loadMap().

Lets do this a bit more generic. Let's modify our loadMap() first:
void loadMap(const std::string& in_filename){ // ... Do extensive work // Notify that loading is done syncToMainLoop([]() { startGame(); });}Simple function call, with inline code block. This is called a lambda. In previous C++ or C, you would have to define a function and pass it as pointer.

Now lets see the implementation of syncToMainLoop.
#include #include #include std::queue> syncQueue;std::mutex syncMutex;void syncToMainLoop(std::function in_callback){ syncMutex.lock(); syncQueue.push(in_callback); syncMutex.unlock();}The std::function is the new way of doing function pointers in C++. The queue is used to pile up multiple sync request in case multiple happen during a single frame. The mutex is there to prevent the queue from being accessed in multiple places at the same time.

Now we just need to add this to the main loop:
void mainLoop(){ while (true) { // Do the sync requests syncMutex.lock(); while (!syncQueue.empty()) { auto callback = syncQueue.front(); // Get the next in line callback(); // Call it syncQueue.pop(); // Remove it } syncMutex.unlock(); game.update(); game.draw(); }}Now you can sync back to the main thread during any async loading. Here is the full code of the example:
#include #include #include #include std::queue> syncQueue;std::mutex syncMutex;void mainLoop(){ while (true) { // Do the sync requests syncMutex.lock(); while (!syncQueue.empty()) { auto callback = syncQueue.front(); // Get the next in line callback(); // Call it syncQueue.pop(); // Remove it } syncMutex.unlock(); game.update(); game.draw(); }}void syncToMainLoop(std::function in_callback){ syncMutex.lock(); ?syncQueue.push(in_callback); syncMutex.unlock();}void onNewGame(){ // Load the map, asynchronously std::async(loadMap, "level1-1.map"); // return and continue normal execution... render your animated loading screen on your mainloop}void loadMap(const std::string& in_filename){ // ... Do extensive work // Notify that loading is done syncToMainLoop([]() { startGame(); });}

Daivuk

Daivuk

Sign in to follow this  
  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!