1 year ago
#378713
Oro
Sharing variables between threads in C++ on Windows
I need to communicate with robot via sockets (this part works) and I'd like to make a watchdog to monitor if the robot is ready or not.
The communication handling is in while loop until the robot ends it. My thought was to use a bool variable whose value is inverted every time a valid message from robot is received.
In a separate thread also in a while loop the bool variable would be periodically checked against another bool with value from previous cycle to detect a change - a new command. When a change occurs, it should set watchdog state as ready. After some time without a command the watchdog is set to inactive.
The problem is that even when I see a new command received, the watchdog is still inactive (the output is almost always "-"). I tried to use mutex to eliminate problems in accessing variables from different threads but I might got it wrong - it didn't seem to help. Could you please give me a hint where the problem(s) might be?
The whole code is here:
#include<io.h>
#include<stdio.h>
#include<winsock2.h>
#include<ws2tcpip.h>
#include<windows.h>
#include<iostream>
#include<thread>
#include<mutex>
#pragma comment(lib,"ws2_32.lib")
const ULONGLONG wdMaxTime = 10000;
bool wdAlive = false; // Robot ready? true = ready
bool wdState = false; // Changing value after a command is received
bool wdStateShadow = false; // Last value of wdState
std::mutex mtx;
DWORD WINAPI myThreadWatchdog()
{
ULONGLONG start = GetTickCount64();
while (true)
{
Sleep(1000);
mtx.lock();
// This should be executed every time a command is received..
// ...but it's not
if (wdState != wdStateShadow)
{
wdAlive = true;
start = GetTickCount64();
wdStateShadow = wdState;
}
// Too long without a command, watchdog is inactive
if (GetTickCount64() - start > wdMaxTime) wdAlive = false;
// Debug output
if (wdAlive) printf("+");
else printf("-");
mtx.unlock();
}
return 0;
}
int main(int argc, char* argv[])
{
WSADATA wsa;
SOCKET s, new_socket;
struct sockaddr_in server, client;
int c;
size_t d;
char message_received[128];
std::thread worker_threadA(myThreadWatchdog);
if (WSAStartup(MAKEWORD(2, 2), &wsa) != 0)
{
printf("Failed. Error Code : %d", WSAGetLastError());
return 1;
}
if ((s = socket(AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET)
{
printf("Could not create socket : %d", WSAGetLastError());
}
inet_pton(AF_INET, "192.168.0.167", &server.sin_addr);
server.sin_family = AF_INET;
server.sin_port = htons(9999);
if (bind(s, (struct sockaddr*)&server, sizeof(server)) == SOCKET_ERROR)
{
printf("Bind failed with error code : %d", WSAGetLastError());
}
listen(s, 3);
c = sizeof(struct sockaddr_in);
do
{
new_socket = accept(s, (struct sockaddr*)&client, &c);
if (new_socket == INVALID_SOCKET)
{
printf("accept failed with error code : %d", WSAGetLastError());
}
memset(message_received, 0, sizeof(message_received));
d = recv(new_socket, message_received, sizeof(message_received) - 1, 0);
// Now we have a command, let's handle it
printf("Received: %s\n", message_received);
const char* message;
if (strncmp(message_received, "DATA", sizeof(message_received)) == 0)
{
message = "Data sent.";
send(new_socket, message, strlen(message), 0);
}
// Flip the bool value for watchdog thread to notice
mtx.lock();
wdState = !wdState;
mtx.unlock();
} while (strncmp(message_received, "END", sizeof(message_received)) != 0);
closesocket(s);
WSACleanup();
return 0;
}
c++
multithreading
mutex
0 Answers
Your Answer