1
\$\begingroup\$

I want my thread to run seperately, but I want to be able to keep executing the game loop without killing the thread scope, If I remove the join there is a crash ?

What can I do ?

My desired result is for the unit just to wait while the path is being calculated, but I don't want the game loop to pause, now while it is alot quicker, there are freezes of atleast 1 second over long distances while its stuck in the pl and hpl threads.

thread pl

thread hpl

are my seperate pathfinding threads.

path requester--- only execute path for selected unit if there is a unit requesting in the pathingrequester vector, this is stored in an abstract class. The units waypoints get pushed onto its waypoint queue when its done.

void pathingrequester()
{
    // executes the requested paths for A* pathing
    if (AWorld.RequestingPath.empty() != true)
    {
        AWorld.RequestingPath.front();
        //cout << "Completed "<< AWorld.RequestingPath.front()->pf_Source->warpPointNO<<"to:"<< AWorld.RequestingPath.front()->UltimateDestination->warpPointNO<<endl;
        astarpathfinder(AWorld.HiFiWaypoints, AWorld.RequestingPath.front()->pf_Source->ret_posX(), AWorld.RequestingPath.front()->pf_Source->ret_posY(),
        AWorld.RequestingPath.front()->UltimateDestination->ret_posX(), AWorld.RequestingPath.front()->UltimateDestination->ret_posY(), AWorld.RequestingPath.front(), AWorld.lines, AWorld.pointsInLine, MainAB.Path);
        AWorld.RequestingPath.pop_front();
    }
}

------------------------------- program execution loop

while (ConqEngine->IsRunning())
{
    bool running = ConqEngine->IsRunning();
    // Draw the scene
    ConqEngine->DrawScene();
    updateTime = ConqEngine->Timer(); // Frame Timer

    thread pl(pathingrequester);
    thread hpl(hpa_pathin_requester);


    if (MainAB.bmenuloop)
    {
        initial_menu_loop(MainAB.loaded_men_interface, MainAB.bmenuloop, MainAB.bloadloop, MainAB.binfoloop ,textControl);
    }
    else if (MainAB.bloadloop)
    {
        preconqload(MainAB.bloadloop, MainAB.bgameloop, MainAB.startingx, MainAB.pipnumber);
    }
    else if (MainAB.binfoloop)
    {
        if (ConqEngine->AnyKeyHit())
        {
            ConqEngine->RemoveSprite(MainAB.LoadingSprite);
            MainAB.binfoloop = false;
            MainAB.bmenuloop = true;

        }
    }
    else if (MainAB.bgameloop)
    {

        thread gl(gameloop, ref(myFont), ref(myFont2), ref(textControl));
        gl.join();

    }

    hpl.join();
    pl.join();

Can anyone give me good example code how to set this up ? or a library that helps handle this?

\$\endgroup\$
1
\$\begingroup\$

Disclaimer; I am not a C++/gaming dev expert, but happened to run across your question, and think I understand the problem..

Every single loop you call this every every thread;

thread.join();

This design of your program pretty much results in the entire loop taking as long as the longest running thread.

I would recommend making the threads all run completely independently and joining after the game loop is done. Sharing of information and joining can be two different things.

Additionally, you're intializing the threads inside the game loop, also address this; the threads that help the 'main'loop which also draws, should not block it; they should just 'feed' it the info it needs to render the state of the program.

The data into which the other threads feed, and the reading of the data should be mutexed (with the same mutex) - Not the best design possible; but it should significantly help your problem.

Update: In Pseudo; I would refactor your code to look roughly like this:

std::mutex stateMutex;
GameState state;
thread pl(pathingrequester); //updates 'the state' (should use stateMutex also)
while (ConqEngine->IsRunning())
{
    GameState copyOfGameState;
     {
      //lays a lock only for the duration lock_guard is in scope, always releases, even when exceptions occur, thanks to RAII
      std::lock_guard<std::mutex> lock(stateMutex);
      copyOfGameState = state;
     }
    ... code here that renders using state ...
}

Note; making a copy is not useful if it is highly costly (i.e. moreso than rendering, if the main loop does this; I am not sure it does.)

\$\endgroup\$
  • \$\begingroup\$ not sure what you mean sorry, the game loop is seperate from the main execution loop ? how can I seperate it out ? \$\endgroup\$ – RNewell122 Aug 29 '17 at 18:22
  • \$\begingroup\$ @RNewell122 I've added a pseudocode example; hopefully this gives you the idea of how I would approach the problem, given your situation. Thanks for asking the question btw, I will get into game development myself, and it doesn't hurt to be thinking of this kind of problem :) \$\endgroup\$ – Joeppie Aug 29 '17 at 18:49
  • \$\begingroup\$ sorry what should GameState be? and I think the engine kIRrilicht runs it in a seperate thread anyway but I'm not sure. \$\endgroup\$ – RNewell122 Aug 29 '17 at 19:11
  • \$\begingroup\$ Sorry, I may not be able to help you. But the problem, as it appears to me is that the while loop in your question, can never complete until all three threads are created, and subsequently complete. The 'other' threads should be created outside of the while, and they should also join the main thread outside of the while loop. Data shared between the threads must be mutxed; that is to say, both the reading and writing operations may not be running at the same time; a mutex is necessary for that. \$\endgroup\$ – Joeppie Aug 29 '17 at 19:14
  • \$\begingroup\$ I get that, but what is the game state ? how do I create and execute them in the while loop if they are declared outside the loop ? \$\endgroup\$ – RNewell122 Aug 30 '17 at 11:43

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.