MADEAPPS / newton-dynamics

Newton Dynamics is an integrated solution for real time simulation of physics environments.
http://www.newtondynamics.com
Other
945 stars 182 forks source link

Poll status state of an asynchronous update? #139

Closed germangb closed 5 years ago

germangb commented 5 years ago

Hi, is there a way to poll if a NewtonUpdateAsync has finished?

I think I can use a NewtonWorldUpdateListenerCallback to update an atomic bool. Is there a simpler or better solution?

Thanks in advance

JulioJerez commented 5 years ago

the is not direct way, since is running on a sperate thread, but you can call NewtonWaitForUpdateToFinish (m_world); and when the function returns when the update is complete.

using a listen is a big mistake NewtonWorldUpdateListenerCallback because if you do a sub step it will make listen calls.

JulioJerez commented 5 years ago

you do not want to call NewtonWaitForUpdateToFinish each time you make an update because I will defect the purpose of a asynchronous update. but you can make a thread that you can use to make engine changes, that thread will be sleeping and each time you what to make an engine change, you call the thread and what is does is that is call NewtonWaitForUpdateToFinish and when is return you can do the modifications. many people do it in different ways, that why I do not add any special funtionality.

germangb commented 5 years ago

I intended to poll the world until completion in an event loop (still not sure if it's a good idea haha..). I think I can work with this though. Thank you for the tips, and your work on this project in general

JulioJerez commented 5 years ago

"I intended to poll the world until completion in an event loop..." a simple way to handle this something like this

at the very begging of your loop you call NewtonWaitForUpdateToFinish, the you ar free to make any change to the engine

void Updateloop()
{
      // sync engine with application
     NewtonWaitForUpdateToFinish()
   // do all changes to physics engine engine here

   //  call for a newton update synbc or async, teh asy will retur immidially and will run concurrent until the update is completed or will block on teh nex call to NewtonWaitForUpdateToFinish is called or  
   NewtonUpdateAsync (...)

   // do all graphics and rendering stuff concurrent with phycs update  
}

This does not run 100% asynchronous, but it runs your application concurrent with the graphics frame by frame, so the time will be which ever takes loonger to complete, if you graphics update is longer than the simulation time then you practically get the physics for free, provided you have more than one core. if the physcs takes longer then you will be bound by the physics time.

germangb commented 5 years ago

Mi idea was to run the simulation headless, in an event loop while doing IO and other asynchronous tasks. The framework that I use is polling-based, that's why I was looking for a way to poll the simulation step.

JulioJerez commented 5 years ago

oh I see, I assume you are running some offline process, you can do some as simple as this in pseudo code,

class dgUpdate
{
    bool IsBusy() const
    { 
        return m_isbusy;
    }

    void BlockUpdate()
    {
        dgInterlockedExchange(&m_blocked, 1);
                while (m_isBusy) ThreadYield();
    }

    void UnBlockUpdate()
    {
        dgInterlockedExchange(&m_blocked, 0);
    }

    void Execute (dgInt32 threadId)
    {
        while (!m_terminate) {

            if (!m_blocked) {
                                dgInterlockedExchange(&m_isBusy, 0);
                                NewtonWaitForUpdateToFinish();
                                dgInterlockedExchange(&m_isBusy, 1);
                NewtonUpdate(...);
            } else {
                ThreadYield();
            }

        }
    }

    int m_blocked;
    int m_terminate;
    int m_isbusy;
}

you complet the thread and in teh update it will be perpetually updating as along as is no block the in you pooling code, you check call IsBusy and when it retirm false it means the last upadte was completed, the you can call Blockupdate, this is imprtant because you do no wna to make IO changes and another update update start, so you stop teh update and you doo all teh ypdate the you ccall Unblock again. I have not done in a long time but that hwo I did when I made few plugins, you can test the logic. I hope you get the idea.

JulioJerez commented 5 years ago

I edited, is not difficult to get I going, you must try, this is something coming people do all the time to synchronize background tasks, in fact if you do it liek that you do no even have to use the asycrong update version. because your update is already on a asynchronous thread controll by you. In fact I recommend using the NewtonUpdate instead of teh async update like this:

class dgUpdate
{
    bool IsBusy() const
    { 
        return m_isbusy;
    }

    void BlockUpdate()
    {
        dgInterlockedExchange(&m_blocked, 1);
                while (m_isBusy) ThreadYield();
    }

    void UnBlockUpdate()
    {
        dgInterlockedExchange(&m_blocked, 0);
    }

    void Execute ()
    {
        while (!m_terminate) {
            if (!m_blocked) {
                               dgInterlockedExchange(&m_isBusy, 1);
                NewtonUpdate(...);
                                dgInterlockedExchange(&m_isBusy, 0);
            } 
            ThreadYield();
        }
    }

    int m_blocked;
    int m_terminate;
    int m_isbusy;
}
germangb commented 5 years ago

Yep, I had something similar in mind. I think It can work for my task. Thanks again for taking the time to reply