Почему мой цикл while не запускается после запуска std :: thread? - PullRequest
0 голосов
/ 30 апреля 2019

Я начал делать проект с сетью.Но после настройки std :: thread, while (true) -loop не запустится.

Первое, что я сделал, это настроил std :: thread, который прослушивает новых клиентов.В функции, используемой потоком, есть while (true) -loop, который отлично работает.В главном потоке после инициализации std :: thread serverListener снова находится цикл while (true), который пытается получить данные, но этот цикл не запустится, за исключением случаев, когда я помещаю std :: cout в цикл while передцикл for, но это спамит мою консоль.

Переменные и включения:

#include <SFML/Network.hpp>
#include <iostream>
#include <list>
#include <thread>

#define PORT 1337

unsigned int clientCounter = 0;

sf::TcpSocket clients[5];
sf::Packet packet;

Функция, которую использует std :: thread:

void serverListener() {

    sf::TcpListener listener;
    listener.listen(PORT);

    while (true) {
        if (listener.accept(clients[clientCounter]) == sf::Socket::Status::Done) {
            std::cout << "New client connected: " 
                      << clients[clientCounter].getRemoteAddress() << std::endl;
            clientCounter++;
        }
    }
}

Основная тема:

int main()
{
    std::thread serverListenerThread(&serverListener);

    while(true) {
        //std::cout << "Some message"; <----- when uncomment, the loop works?

        for (int i = 0; i < clientCounter; i++) {

            std::string message = "";
            packet >> message;

            if (clients[i].receive(packet) == sf::Socket::Status::Done) {

                message += std::to_string(i);
                std::cout << message << std::endl;
            }
        }

    }

    return 0;
}

1 Ответ

1 голос
/ 01 мая 2019

Подумайте немного о том, что видит первый поток.Поскольку у вас нет синхронизации между двумя потоками, компилятор предполагает, что они не взаимодействуют, и поэтому значение clientCounter никогда не изменится, пока выполняется внутренний цикл for.Таким образом, цикл всегда будет видеть clientCounter=0, поэтому цикл не будет выполняться.

unsigned int clientCounter = 0;

int main()
{
    std::thread serverListenerThread(&serverListener);

    while(true) {
        for (int i = 0; i < clientCounter; i++) {
            // Never executed, since clientCounter = 0
        }
    }
}

Вы должны сделать clientCounter std::atomic<unsigned int>.Это позволяет компилятору синхронизировать переменную между потоками.В общем, все, что вы разделяете между потоками, должно быть либо атомарным, либо должно быть защищено блокировкой мьютекса.

Добавление сна может помочь, но только по чистой случайности;нет абсолютно никаких причин, почему он должен продолжать работать.В частности, нет необходимости загружать значение clientCounter из памяти между итерациями цикла while, поскольку компилятор «знает», что оно никогда не записывается в основной поток.Таким образом, перезагрузка будет излишней.

...