Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: [SOLVED]Problem with multi-threading  (Read 4098 times)

0 Members and 1 Guest are viewing this topic.

filipekczek7

  • Guest
[SOLVED]Problem with multi-threading
« on: June 06, 2016, 04:59:04 pm »
(In the beginning, sorry for my english ;))

I've got problem with threads. I'm making network game. Singleplayer mode is done, but multiplayer online mode is a bit laggy. This is my previous sending and receiving data function:
//////////////////////////////////////////////////////Server
void Engine::serverNetworkUpdate()
{
        Lock lock(mutex);

        float data;

        while (game)
        {
        //sending data
                data = otherData;
                socket->send(sendingPacket);

                sendingPacket.clear();

                //receiving data
                socket->receive(receivingPacket);
                if (receivingPacket >> data)
                {
                        otherData = data;

                        receivingPacket.clear();
                }
        }
}

//////////////////////////////////////////////////////Client
void Engine::clientNetworkUpdate()
{
        Lock lock(mutex);

        float data;

        while (game)
        {
                //receiving data
                socket->receive(receivingPacket);
                if (receivingPacket >> data)
                {
                        otherData = data;

                        receivingPacket.clear();
                }

                //sending data
                data = otherData;
                socket->send(sendingPacket);

                sendingPacket.clear();
        }
}

This function is launching by a thread. I deduced that it would be better to separate send and receive on two different threads. Program would not have to wait to receive data and in meantime would send other data. OK, just divide sending and receiving function and launch two threads. There are these functions:
//////////////////////////////////////////////////////Server
void Engine::serverSending()
{
        Lock lock(mutex);

        float data;

        while (game)
        {
                data = otherData;
        sendingPacket << data;
                socket->send(sendingPacket);

                sendingPacket.clear();
        }
}

void Engine::serverReceiving()
{
        Lock lock(mutex);

        float data;

        while (game)
        {
                //receiving data
                socket->receive(receivingPacket);
                if (receivingPacket >> data)
                {
                        otherData = data;

                        receivingPacket.clear();
                }
        }
}

//////////////////////////////////////////////////////Client
void Engine::clientSending()
{
        Lock lock(mutex);

        float data;

        while (game)
        {
        data = otherData;
                sendingPacket << data;
                socket->send(sendingPacket);

                sendingPacket.clear();
        }
}

void Engine::clientReceiving()
{
        Lock lock(mutex);

        float data;

        while (game)
        {
                socket->receive(receivingPacket);
                if (receivingPacket >> data)
                {
                        otherData = data;

                        receivingPacket.clear();
                }
        }
}

I initiate these threads in constructor:
Engine::Engine(..., int whatMode)
{
    //... other code

    else if (whatMode == 10)
        {
                sendingThread = new Thread(&Engine::serverSending, this);
                receivingThread = new Thread(&Engine::serverReceiving, this);
                runGameOnlineServer();
        }
        else if (whatMode == 11)
        {
                sendingThread = new Thread(&Engine::clientSending, this);
                receivingThread = new Thread(&Engine::clientReceiving, this);
                runGameOnlineClient();
        }
}

I'm launching these threads in runGameOnlineServer() and runGameOnlineClient() functions:
//////////////////////////////////////////////////////Server
void Engine::runGameOnlineServer()
{
        receivingThread->launch();
        sendingThread->launch();

    while (game)
    {
        //events, updating, drawing etc.
    }
}

//////////////////////////////////////////////////////Client
void Engine::runGameOnlineClient()
{
        receivingThread->launch();
        sendingThread->launch();

    while (game)
    {
        //events, updating, drawing etc.
    }
}

This is destructor:
Engine::~Engine()
{
        //closing thread and socket, if game was online
        if (gameMode == 10 || gameMode == 11)
        {
                sendingThread->terminate();
                receivingThread->terminate();
                delete sendingThread;
                delete receivingThread;
                socket->disconnect();
        }
}

Simple in theory. But... My second thread doesn't launch. So if server first launch sendingThread, receivingThread doesn't launch. The same with client: client first launch receivingThread, so sendingThread doesn't launch. Server sends data (in this case left player and ball positions), but doesn't receive data (in this case right player position, it's Pong game). Client receives data, but doesn't send. To make sure I checked console output: only one thread was launched.

Does anyone know what's wrong? Why only one thread works?
« Last Edit: June 06, 2016, 06:55:58 pm by filipekczek7 »

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Re: Problem with multi-threading
« Reply #1 on: June 06, 2016, 06:38:49 pm »
You're using your mutex terribly wrong. By locking entirely all your functions with the same mutex, you're canceling any attempt to run more than one thread because as soon as one function hols the lock, no other function can run until it has finished -- which never happens for those that run an infinite loop.

I suggest that you read more about the theory, and practice more with simpler exercises, to fully understand these mechanisms. Multi-threading is a complex subject ;)
Laurent Gomila - SFML developer

filipekczek7

  • Guest
Re: Problem with multi-threading
« Reply #2 on: June 06, 2016, 06:55:44 pm »
One mutex for one fucntion? I didn't expect that... (yes, I have to learn more ;))

OK, I changed that, I added one more mutex and... It's working :) Server and client work on the same computer, so I have to check it on two different computers, but I think problem is solved.

Thank you very much for help :)

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Re: [SOLVED]Problem with multi-threading
« Reply #3 on: June 06, 2016, 09:04:14 pm »
Quote
One mutex for one fucntion?
No. One mutex for one thing to protect against concurrent access. It really is more complex than what you seem to think. Mutexes are not magical objects that you just have to throw randomly in your code to make it work fine with multiple threads. You have to think carefully about which variables are accessed by which threads, and what must be protected, why, and when exactly.

Quote
I think problem is solved
I don't think so ;)
Laurent Gomila - SFML developer

filipekczek7

  • Guest
Re: [SOLVED]Problem with multi-threading
« Reply #4 on: June 07, 2016, 08:11:13 am »
Hm, I was wondering if I am using mutexes and locks in a wrong way. OK, I'm gonna remove these mutexes for now, I really have to learn more :)
« Last Edit: June 07, 2016, 04:34:35 pm by filipekczek7 »