Forum C# Multithreading issue, what to lock?

Multithreading issue, what to lock?

Postby whitershores » July 23rd, 2012, 7:25 pm

I am working on a game, where only player input is transmitted, so the Server needs to stay in sync with all Clients, ie needs to be fully deterministic. That is if anything updates just Once in the wrong order -> desync and all bets are off( an RTS lockstep game )

As far as I understood the multithreading works like if there are some 'spikes' the next 'AddTimer' event can be called before the previous one finished, so this can result in 2 gameloop updates running simultaneously (http://playerio.com/forum/csharp/server-lag-spikes-t2061), and the only way to solve this is via a 'Lock'.
This is a simplified gameloop:

Code: Select all
void gameloop(timedelta)
{
   _fullFrameStartTime+= timedelta;
   _lockstepProtocol.update();
         
   for(int i = 0; i < _worldState.entities.Count; i++)
        _worldState.entities[i].update(timedelta);

   for(int j = 0; j < _worldState.players.Count; j++)
        _worldState.players[j].update(timedelta);            
}
class entity
{
  vector2D _position;

   void update(timedelta)
   {
      _position *= timedelta;
   }
}

- what do I need to lock out of these? is it enough if I just lock '_worldState'? or do I have to individually lock each List/Object/Entity/etc that is accessed via the _worldstate?

Ideally, as it is a lockstep deterministic game, everything would need to behave as a single threaded app, and NOTHING should be touched by another thread while the previous state update has not finished completely.

Help?!:)
whitershores
Paid Member
 
Posts: 88
Joined: June 21st, 2011, 4:19 pm

Re: Multithreading issue, what to lock?

Postby Henrik » July 24th, 2012, 11:03 am

Simpler solution: Don't use AddTimer. Have your gameloop method use ScheduleCallback instead to schedule itself after (interval - execution time) milliseconds. That way you will never have overlapping executions (and don't need any complicated locking whatsoever) and you get to handle the case explicitly where execution time is larger than your desired interval.
Henrik
.IO
 
Posts: 1880
Joined: January 4th, 2010, 1:53 pm

Re: Multithreading issue, what to lock?

Postby whitershores » July 24th, 2012, 12:26 pm

Very interesting idea, so you are suggesting to use a ScheduleCallback with the the desired gameloop interval, at the end of the last statement in each gameloop() function right?


Henrik wrote:and you get to handle the case explicitly where execution time is larger than your desired interval.


- I am not 100% sure what you meant here? What should i do ?
whitershores
Paid Member
 
Posts: 88
Joined: June 21st, 2011, 4:19 pm

Re: Multithreading issue, what to lock?

Postby Henrik » July 24th, 2012, 1:21 pm

So you want your gameloop to run every interval, say 100ms. But if you call ScheduleCallback at the end of your gameloop with that number, your gameloop will execute every 100ms + the execution time of it. So if it takes 50ms to run a gameloop, it will run every 150ms, so you have to handle that, something like this:

Code: Select all
private void gameLoop() {
    DateTime start = DateTime.Now;

    //...all your code here...

    TimeSpan executionTime = DateTime.Now - start;
    if (executionTime.TotalMilliseconds > 100) {
        //Uh oh, it took longer than 100ms to run this, maybe do something special...?
    }

    //Run again
    ScheduleCallback(gameLoop, Math.Max(0, 100 - (int)executionTime.TotalMilliseconds));
}
Henrik
.IO
 
Posts: 1880
Joined: January 4th, 2010, 1:53 pm

Re: Multithreading issue, what to lock?

Postby whitershores » July 24th, 2012, 2:11 pm

That sounds like a great suggestion :)

Btw I plan to run the gameloop as fast as I can, so I will probably not even worry about that, what is the minimum
ScheduleCallback delay which is still reliable?
whitershores
Paid Member
 
Posts: 88
Joined: June 21st, 2011, 4:19 pm

Re: Multithreading issue, what to lock?

Postby whitershores » July 24th, 2012, 3:07 pm

Also

does the ScheduleCallback terminate if I call it to Stop before the delay expired ?

Code: Select all
_timer = _playerIOGame.ScheduleCallback(run, 100);
_timer.Stop()


- IE if I call stop after 50ms then the run() function will not be called right?
whitershores
Paid Member
 
Posts: 88
Joined: June 21st, 2011, 4:19 pm

Re: Multithreading issue, what to lock?

Postby Henrik » July 24th, 2012, 3:11 pm

It's incredibly hard to make any recommendations, it depends completely on your game, how much data you send out to clients each gameloop, how you deal with client lag, and so on. But if I have to pull a number out of thin air: Start with every 200ms and work your way from there until you have the right tradeoff between network lag and bandwidth usage and update speed.
Henrik
.IO
 
Posts: 1880
Joined: January 4th, 2010, 1:53 pm

Re: Multithreading issue, what to lock?

Postby Henrik » July 24th, 2012, 3:12 pm

whitershores wrote:does the ScheduleCallback terminate if I call it to Stop before the delay expired ?

Yes.
Henrik
.IO
 
Posts: 1880
Joined: January 4th, 2010, 1:53 pm

Re: Multithreading issue, what to lock?

Postby whitershores » July 24th, 2012, 3:29 pm

Henrik wrote:It's incredibly hard to make any recommendations


- no no sorry, I just simply asked for the live server /playerio technical capabilities, as of how often the ScheduleCallback can be called?

Somewhere I've read 25ms, but that was for the AddTimer?
whitershores
Paid Member
 
Posts: 88
Joined: June 21st, 2011, 4:19 pm

Re: Multithreading issue, what to lock?

Postby Pawel Wozniak » December 16th, 2012, 4:27 pm

I have the same problem (overlapping) but the code is called by GotMessage.

I wonder if its good idea to set _receivingMessagesLocked = true while code is executed and hold all upcoming "GotMessage"s then in a queue?
Pawel Wozniak
Paid Member
 
Posts: 96
Joined: October 14th, 2012, 10:47 pm

Re: Multithreading issue, what to lock?

Postby Pawel Wozniak » December 16th, 2012, 4:32 pm

... and what if another GotMessage will be called before the first will set _receivingMessagesLocked property to true?
Pawel Wozniak
Paid Member
 
Posts: 96
Joined: October 14th, 2012, 10:47 pm

Re: Multithreading issue, what to lock?

Postby olgeorge » January 30th, 2013, 7:04 pm

Same question, is it a good solution lock on GotMessage like Pawel suggested? The code was probably multithreaded to handle many calls to the server, and so if I lock on GotMessage, I wouldn't be able to handle that many clients?
olgeorge
 
Posts: 12
Joined: November 9th, 2012, 9:20 am

Re: Multithreading issue, what to lock?

Postby Henrik » January 30th, 2013, 8:23 pm

This solution seems a bit weird to me. Check my other response for how to make a synchronized queue of messages, and use that to process all messages. To execute the first message directly in GotMessage, and then queue up any extra messages that you get while it's executing seems like a lot of extra work to me, and a place where it's easy to introduce bugs.
Henrik
.IO
 
Posts: 1880
Joined: January 4th, 2010, 1:53 pm

Re: Multithreading issue, what to lock?

Postby williamholdin » June 24th, 2016, 6:06 am

Even if one instruction runs on a CPU at any given time, computer programs comprise a lot more than just atomic assembly instructions. So for example, writing to the console (or a file) means you have to have to lock to ensure it works like you want. Only one thread can lock the object at a time, and any contending threads are blocked until the lock is released. If more than one thread contends the lock, they are queued on a “ready queue” and granted the lock on a first-come, first-served basis. More about...Thread Lock

William
williamholdin
 
Posts: 1
Joined: June 24th, 2016, 6:05 am


Return to C#