1 year ago

#378713

test-img

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

Accepted video resources