Skip to main content
GameDev.net gamedev.net
🔒 Locked

Question on Thread Sync

Started by Trentelshark Feb 25, 2008 at 10:13 PM 3 replies 750+ views
Original Post
Trentelshark
Trentelshark
Hi, I have what is hopefully a quick question about thread synchonization. I have a wrapper class for a TCP socket with the receive running in a seperate thread and a seperate module handling the send. To avoid lock issues, I have defined a mutex within the TCP wrapper itself and ensure to lock it immediately upon attempting to access the socket, so for example in pseudocode:

// called by a class managing the socket
void send( CMessage& : msg )
{
   m_mutex.Lock();
   sendto( blah );
   m_mutex.Unlock();
}

// running in seperate thread
int receive( void )
{
   while( bRun )
   {
      m_mutex.Lock();
      receivefrom( blah );
      // if data do something with it
      m_mutex.Unlock();
   }
}


I believe I am perfectly fine in this case but for some reason I had a nagging voice in the back of my head telling me the handler that calls the send should call mutex.Lock() before calling object->send(). This mutex would also be provided to the wrapper class executing the receive as a copy upon construction so if it is in the process of a receive that I can't even step into the object's memory space. Basically looking for some input here since I believe my solution will suffice (I'm not accessing any variables before locking the object) but just wanted to be certain since I'm second guessing myself. Thanks!
Sandman
Sandman
While I haven't mucked about with networking code for a long time, the mutex logic doesn't look right to me.

If receiveFrom is a blocking call that waits for data, then you will not be able to send data unless you receive some data first. That doesn't make a lot of sense.

If it's not a blocking call, i.e it polls for data and returns whether it gets it or not, then you're basically spinning on that data and making poor use of cpu time.

I don't think you want a mutex at all; what you need is a socket implementation that is designed for asynchronous operation.
Antheus
Antheus
Why are you using locks in the first place.

With TCP, you need either thread-per socket, or process all network traffic in one thread.

What happens, if thread A and B both receive data for same socket, but process it in reverse order?

Besides, send and receivefrom are thread-safe (almost certainly for any modern socket implementation). Your lock is redundant.
Trentelshark
Trentelshark
Sandman,

I see what you're saying. The socket itself will poll for data and if none is available it immediately gives up its timeslice and goes back to a "wait" state. If data is received all the method does is generates an event via my event system and gives up its timeslice. I also have a means to force checkign of the socket if the user needs to in the event they want to control when and how often its checked, this was just a quick and dirty example.

After sleeping on it last night I realised what I was worried about and it had to do with the Send call itself. If for some reason two sends come in within very quick succession and the receive is blocking the potential exists that the original message passed in will never be sent as it will be replaced by the second message tossed at the method. To workaround at least this issue (the module does still need a lot of work as you indicated) I've decided to implement a CThreadSafe (or Module) class which exposes a Lock and Unlock method and contains a mutex object as its member. So, my code from above could be reworked so the mutex is locked BEFORE I event make the send call as follows:

Obj socketObj;// time to sendsocketObj.Lock();socketObj.Send( msg );socketObj.Unlock();// reworked send, already got the lock before I step invoid send( CMessage& : msg ){   sendto( blah );}

As i said, this is mainly to ensure that should two modules access the same object that they won't stomp on one another. As this is not the networking forum I'll avoid a discussion here on polling the socket and post any questions, etc. in the networking forum if anything else crops up.

Thanks again for your input!
Trentelshark
Trentelshark
Quote:
Original post by Antheus
Why are you using locks in the first place.

With TCP, you need either thread-per socket, or process all network traffic in one thread.

What happens, if thread A and B both receive data for same socket, but process it in reverse order?

Besides, send and receivefrom are thread-safe (almost certainly for any modern socket implementation). Your lock is redundant.

Slipped that post in before I got my other reply up! I believe this implementation appears confusing because I have a number of other classes which the network implementation relies on. Namely the event system which is used by the socket to inform the application that data has been received. If a send is to be processed an event is received by the socket manager which forwards this off to the socket requested by the client. I didn't want to have a single callback saying if( recv ){ } if( datatosend ){ send } because that additional send seemed to be a waste to me so I seperated the calls out where-in the recv runs on the thread and a send is a (sort of) synchronous call.

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.