0
\$\begingroup\$

I am trying to set up a basic toy example of how a loading screen would work in SDL. Here is my code below.

#include <iostream>
#include <SDL2/SDL.h>
#include <SDL2/SDL_thread.h>

#define DELAY  10

std::string status = "state 0";

static int LoadThread(void* data)
{
    //Delay to simulate loading
    SDL_Delay(DELAY);
    status = "delay 0";
    SDL_Delay(DELAY*10);
    status = "delay 1";
    SDL_Delay(DELAY*100);
    status = "delay 2";
    SDL_Delay(DELAY*5);
    status = "delay 3";
    SDL_Delay(DELAY*6);
    status = "delay 4";
    SDL_Delay(DELAY*5);
    status = "delay 5";
    SDL_Delay(DELAY*2);

    status = "finished";
    return 0;
}

int main(int argc, char *argv[])
{      
    SDL_Thread *p = SDL_CreateThread(LoadThread, "LoadingAssetsThread", nullptr);
   
    std::string currentStatus = status;

    while(true)
    {        
        if (status != currentStatus)
        {
            std::cout << status << " " << tState << std::endl;
            currentStatus = status;
        }

        if (currentStatus == "finished") break;
    }        
        

    SDL_WaitThread(p, nullptr);
    
    return 0;
}

Basically I want to show a series of lines of text stating what is the current asset that is being loaded, i.e. textures, sound, etc one after as they complete loading in the separate thread.

Is this the right approach? The reason being, in my real world code, I noticed when optimization is turned on (-O3 option in g++) sometimes certain steps in "currentStatus" will be skipped over and won't display in the main thread. I am using a std::cout to illustrate but in reality there is a function that draws the text to a SDL window.

Put another way, there is a variable that the loading function has to update as it sequentially loads one asset after another and the main game loop renders a different message to the player based on what that variable is at any given time during the loading process.

---Update---

After a bit more diagnosing I realize what is happening is that the loading thread is loading some of the assets so fast that it happens within one single update of the main game loop for example:

void loadThread()
{
   state = "loadTiles";
   Load_Tiles();
   state = "loadSound";
   Load_Sound();
   state = "loadGraphics";
   Load_Graphics();
}

if for instance, Load_Tiles and Load_Sound both occur quickly enough then from the perspective of the main game loop it will only see the state as "LoadGraphics". Do I need some way of pausing the loading process until the main thread is updated? I can put in a SDL_Delay() but that seems hacky.

\$\endgroup\$
1
  • \$\begingroup\$ 1. This is undefined behavior, you need to protect the variable with a mutex (or do something else to synchronize access to it between threads). 2. Is this really an issue if the main thread skips a message? To force it to not be skipped you'd have to artificially slow down loading. \$\endgroup\$ Dec 15, 2023 at 2:45

1 Answer 1

-1
\$\begingroup\$

A single valued integer of machine word size(32 or 64 bits) is guaranteed to provide consistent atomic reads and writes across one read-only thread and a single read-write thread.


Define an int or long(see above), or your favorite alias, status variable for each thread and an array of strings to draw.

The string array will help with language translations later on.

Either, if each thread status variable and draw the string from the array.

Or, draw the base text for each of the string values and append the completion values.

This way:

  • No synthetic or synchronizing delays,i.e. mutexes, are needed
  • The string draw order is maintained and nothing completed gets skipped
  • More frequent progress indicators will be shown on slower computers (thread completion percentage).

As a side note setting the optimization level above -O2 is usually overkill and may even lead to decreased run-time performance.

\$\endgroup\$
1
  • \$\begingroup\$ "guaranteed to provide consistent atomic reads" It doesn't, at least not per the standard. I'd just use std::atomic rather than trying to be clever, so when the game starts randomly crashing next time, I can be sure it's not a multithreading bug. (And if as you say single-word operations are atomic by default on your platform, std::atomic and normal types will just compile to the same assembly where appropriate.) \$\endgroup\$ Dec 18, 2023 at 3:32

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .