2
\$\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 Answer 1

2
\$\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\$
6
  • \$\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, 2017 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, 2017 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, 2017 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, 2017 at 19:14
  • 1
    \$\begingroup\$ Its been a very long time since I answered this and accepted but I did finish this during University, and I solved it. :) \$\endgroup\$
    – RNewell122
    Apr 22, 2021 at 9:09

You must log in to answer this question.

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