
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/System.hpp>
#include <iostream>


sf::Mutex GlobalMutex; // This mutex will be used to synchronize our threads


////////////////////////////////////////////////////////////
/// Entry point of the first thread
///
/// \param UserData : User data passed to the thread (here we don't use it)
///
////////////////////////////////////////////////////////////
void MyThreadFunc(void* UserData)
{
    // Lock the mutex, to make sure no thread will interrupt us while we are displaying text
    GlobalMutex.Lock();

    // Print something...
    for (int i = 0; i < 10; ++i)
        std::cout << "I'm the thread number 1" << std::endl;

    // Unlock the mutex
    GlobalMutex.Unlock();
}


////////////////////////////////////////////////////////////
/// Custom thread class
////////////////////////////////////////////////////////////
class MyThread : public sf::Thread
{
private :

    ////////////////////////////////////////////////////////////
    /// This is the function to override as the entry point of the thread
    ///
    ////////////////////////////////////////////////////////////
    virtual void Run()
    {
        // Lock the mutex, to make sure no thread will interrupt us while we are displaying text
        GlobalMutex.Lock();

        // Print something...
        for (int i = 0; i < 10; ++i)
            std::cout << "I'm the thread number 2" << std::endl;

        // Unlock the mutex
        GlobalMutex.Unlock();
    }
};


////////////////////////////////////////////////////////////
/// Entry point of application
///
/// \return Application exit code
///
////////////////////////////////////////////////////////////
int main()
{
    // First way of using sfThread : with a callback function
    sf::Thread Thread1(&MyThreadFunc);
    Thread1.Launch();

    // Lock the mutex, to make sure no thread will interrupt us while we are displaying text
    GlobalMutex.Lock();

    // Print something...
    for (int i = 0; i < 10; ++i)
        std::cout << "I'm the main thread" << std::endl;

    // Unlock the mutex
    GlobalMutex.Unlock();

    // Make sure the first thread has finished before continuing
    Thread1.Wait();



    // Second way of using sfThread : with a derived class
    MyThread Thread2;
    Thread2.Launch();

    // Lock the mutex, to make sure no thread will interrupt us while we are displaying text
    GlobalMutex.Lock();

    // Print something...
    for (int i = 0; i < 10; ++i)
        std::cout << "I'm the main thread" << std::endl;

    // Unlock the mutex
    GlobalMutex.Unlock();

    // Make sure the second thread has finished before exiting
    // Here is it optional, as the sfThread destructor will do it automatically
    Thread2.Wait();

    // Wait until the user presses 'enter' key
    std::cout << "Press enter to exit..." << std::endl;
    std::cin.ignore(10000, '\n');

    return EXIT_SUCCESS;
}

