Reputation: 3
i've started doing a project with networking. But after setting up a the std::thread, the while(true)-loop wont start.
The first thing i have done is setting up the std::thread which is listening for new clients. In the function which the thread is using is a while(true)-loop, which perfectly works. In in the main thread after initializing the serverListener std::thread, is again a while(true)-loop which tries to recieve data, but this loop wont start, except when I put a std::cout in the while-loop before the for-loop, but this spams my console.
Variables and inclusions:
#include <SFML/Network.hpp>
#include <iostream>
#include <list>
#include <thread>
#define PORT 1337
unsigned int clientCounter = 0;
sf::TcpSocket clients[5];
sf::Packet packet;
The function which the std::thread is using:
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++;
}
}
}
Main thread:
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;
}
Upvotes: 0
Views: 210
Reputation: 370
Think for a moment about what the first thread sees. Since you have no syncronisation between the two threads, the compiler assumes they don't communicate and so the value of clientCounter
will never change while the inner for loop is being executed. Thus the loop will always see clientCounter=0
and so the loop doesn't run.
unsigned int clientCounter = 0;
int main()
{
std::thread serverListenerThread(&serverListener);
while(true) {
for (int i = 0; i < clientCounter; i++) {
// Never executed, since clientCounter = 0
}
}
}
You should make clientCounter
an std::atomic<unsigned int>
. This lets the compiler know to synchronise the variable between threads. In general, anything that you share between threads should either be atomic or should be protected by locking a mutex.
Adding a sleep may help but only by pure luck; there is absolutely no reason why it should continue to work. In particular, there is no requirement to load the value of clientCounter
from memory between while loop iterations, since the compiler 'knows' it is never written to in the main thread. Thus, reloading it would be redundant.
Upvotes: 2