Не могу найти ошибку в коде потоков / атомарных значений - PullRequest
0 голосов
/ 16 апреля 2019

Я использую CodeBlocks с компилятором MinGW и библиотекой wxWidgets.

Я пишу программу, которая считывает некоторые данные из микроконтроллера, отправляя сообщения (используя индекс и субиндекс) и получая ответные сообщения с указанными данными.

Мой план состоял в том, чтобы отправлять сообщения одно за другим и ждать ответа, используя __atomic int variables__, чтобы проверить, когда я получаю ответное сообщение.

Это моя функция для отправки сообщения:

typedef std::chrono::high_resolution_clock Clock;
void sendSDO(int index, int subindex)
{
    int nSent = 0;

    atomic_index.store(index);
    atomic_subindex.store(subindex);

    canOpenClient->SDORead(index, subindex);
    auto start = Clock::now();
    nSentMessages++;
    nSent++;
    Sleep(10);

    while ((atomic_index.load() != 0) && (atomic_subindex.load() != 0))
    {
        auto t = chrono::duration_cast<chrono::milliseconds>(Clock::now() - start);
        if(t.count() > 20)
        {
            if (nSent > 5)
            {
                MainFrame->printTxt("[LOG] response not received\n");
                return;
            }
            atomic_index.store(index);
            atomic_subindex.store(subindex);
            canOpenClient->SDORead(index, subindex);
            nSentMessages++;
            nSent++;
            start = Clock::now();
        }
    }
}

Псевдокод устанавливается в atomic int для индекса и субиндекс того, что я хочу, значение, которое я хочу прочитать из микроконтроллера, затем отправьте ему сообщение SDORead(), и если ответ не был получен в течение 20 мс, отправьте сообщение еще раз, до 5 раз.

Для получения сообщений у меня есть __separate thread__ с функцией обратного вызова, которая вызывается, когда я получаю ответное сообщение от контроллера:

void notifyEvent(unsigned char ev_type)
{
    SDO_msg_t msg;
    msg = canOpenClient->Cmd_CustomMessageGet(); //get response message

    if(ev_type == CO_EVENT_SDO_READ)
    {
        if ((msg.index == atomic_index.load()) && (msg.subindex == atomic_subindex.load()))
        {
            //does stuff, like saves message data to set container

            atomic_index.store(0);
            atomic_subindex.store(0);
        }
    }
    if (message data not in container)
        printf("not in container!")
}

Здесь я устанавливаю те же атомарные значения int на 0, когда получено правильное ответное сообщение, и сохраняю данные ответного сообщения

У меня также есть переменные nSentMessages и nReceivedMessages, которые содержат количество отправленных и полученных сообщений. В конце я проверяю, совпадают ли эти значения. Обычно мне это не нужно (так как я жду каждого ответа), я добавляю его в качестве дополнительной меры безопасности.

Теперь на проблему:

1) Моя проблема в функции обратного вызова notifyEvent(), где я предположительно сохраняю данные ответного сообщения в контейнер, но иногда я получаю сообщение «не в контейнере!» из этого заявления if, и я не знаю почему. (Мой контейнер просто установлен нормально set<EDSobject, cmp> container, он не атомарный или что-то еще, поскольку я знаю, что в него не будут одновременно выполняться чтение / запись из разных потоков.)

2) Если вы проверите мою функцию sendSDO(), появится строка Sleep(10). Программа работает нормально с ним, но если я удаляю его, программа возвращает другое значение для nSentMessages и nReceivedMessages - 576 и 575. Это происходит каждый раз, когда я запускаю программу, и я не понимаю, почему.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...