SFML community forums

Help => System => Topic started by: Richy19 on September 07, 2011, 08:49:42 pm

Title: Using threads to load stuff
Post by: Richy19 on September 07, 2011, 08:49:42 pm
I want to use a thread to load all the assets and while this is happening animate a loading screen.

The way I thoughht I would do it is:

Code: [Select]

void loadFiles()
{
    ...
}

sf::Thread loadingThread( &loadFiles);
loadingThread.Launch();

while(loadingThread.isRunning)
{
    Animate and draw loading screen
}


The problem is that there is no way to find out if the thread is still running, it there any way to do this?
Title: Using threads to load stuff
Post by: Laurent on September 07, 2011, 08:57:37 pm
Use a boolean, change it when your thread function ends and test it in your main thread.
Title: Using threads to load stuff
Post by: Richy19 on September 07, 2011, 09:18:10 pm
so

Code: [Select]
bool threadRunning = false;

void loadFiles()
{
 threadRunning = true
    ...
 threadRunning = false
}

sf::Thread loadingThread( &loadFiles);
loadingThread.Launch();

while( threadRunning)
{
    Animate and draw loading screen
}
Title: Using threads to load stuff
Post by: coolhome on September 08, 2011, 08:29:09 am
Yeah that would work. Instead of using global bool you could reference the bool and pass it to the function. I just think it would probably be cleaner code. Here is an example of what i was talking about. Make sure you make things thread-safe! :D

Example:
Code: [Select]

//SFML 2.0
void LoadingThreadFunc(bool &isRunning)
{
isRunning = true;

for(int i = 1; i != 51; ++i)
{
std::cout << "[LoadingThread] " << i << "/50 has been loaded." << std::endl;
sf::Sleep(1);
}

isRunning = false;
}
int main()
{
bool isThreadRunning = false;
sf::Thread loadingThread(&LoadingThreadFunc, isThreadRunning);
loadingThread.Launch();

while(isThreadRunning)
{
//Run the state of displaying progress and what not.
}

loadingThread.Wait();
system("PAUSE");

return false;
}
Title: Using threads to load stuff
Post by: Richy19 on September 08, 2011, 10:56:13 am
Why do you have

loadingThread.Wait();
Title: Using threads to load stuff
Post by: Contadotempo on September 08, 2011, 04:25:03 pm
Quote from: "Richy19"
Why do you have

loadingThread.Wait();

Here: http://www.sfml-dev.org/tutorials/1.6/system-threads.php
On the section: Terminating a thread

Quote
The only way to safely terminate a running thread is simply to wait for it to finish by itself. To wait for a thread, you can use its Wait() function


Though the tutorial is for SFML 1.6, some parts might still apply to 2.0.
Title: Using threads to load stuff
Post by: Laurent on September 08, 2011, 04:35:59 pm
The destructor calls Wait(), so there's no need to explicitely call it unless you want to wait before the thread instance is destroyed.
Title: Using threads to load stuff
Post by: Richy19 on September 08, 2011, 04:52:05 pm
Passing it to the function as a reference didnt work, but using a global variable did
Title: Using threads to load stuff
Post by: Laurent on September 08, 2011, 05:32:12 pm
You should use a pointer instead. References can't be forwarded properly by sf::Thread to the threaded function, you'd have to use a wrapper like boost::ref.
Title: Using threads to load stuff
Post by: MorleyDev on September 08, 2011, 05:42:36 pm
Also it's probably best to declare that bool as volatile. Otherwise when you compile the Release build using the highest levels of optimisation the compiler may optimise it out and you enter an endless loop, since in a single threaded environment that would be a completely apt optimisation.

Even languages that seem pretty well geared for multithreading don't seem to have compilers thread-aware enough to avoid those kinds of optimisations without prompts from the programmer.

And don't set the bool to true in the actual loop, either do it before the thread starts or wait for it to become true before you start looking for it to become false. There's no guarantee the OS thread scheduler won't screw you over and have enough of a nanosecond delay that the while won't be checked before the bool is assigned.  It's the kind of bug that could happen 1 in 100 runs and is why multithreading, even the simple stuff, is considered so difficult: It's so easy to do something that seems like it would work, and does in 95% of cases, but will fail at seemingly random times.
Title: Using threads to load stuff
Post by: Richy19 on September 08, 2011, 08:59:15 pm
I tried this:

Code: [Select]
void LoadingThreadFunc(volatile bool *isThreadRunning)
{
    // isThreadRunning = true;

    for(int i = 1; i != 51; ++i)
    {
        std::cout << "[LoadingThread] " << i << "/50 has been loaded." << std::endl;
        sf::Sleep(10);
    }

    *isThreadRunning = false;
}

int main()
{

    volatile bool *isThreadRunning;// = true;
    *isThreadRunning = true;

    sf::Thread loadingThread(&LoadingThreadFunc, isThreadRunning);
    loadingThread.Launch();

    std::cout << isThreadRunning << std::endl;

    while(*isThreadRunning)
    {
        std::cout << "Loading" << std::endl;
    }
    return 0;
}


but it just crashes
Title: Using threads to load stuff
Post by: Laurent on September 08, 2011, 10:38:08 pm
You're declaring and using a pointer to a bool that is not initialized. You should rather declare a plain bool and pass its address.