Удаление и восстановление синглтона в C ++ - PullRequest
0 голосов
/ 07 декабря 2009

У меня есть приложение, которое работает на управляющем оборудовании, связанном с различными датчиками. При загрузке приложения он проверяет отдельные датчики один за другим, чтобы увидеть, существует ли надлежащая связь с датчиком в соответствии с предварительно определенным протоколом.

Теперь я реализовал код для проверки связи с отдельным датчиком в виде одноэлементного потока, и далее следует функция запуска, он использовал системный вызов select и канал для межпроцессного взаимодействия, чтобы сигнализировать об окончании потока.

void SensorClass::run()
{
    mFdWind=mPort->GetFileDescriptor();
    fd_set readfs;
    int max_fd = (mFdWind > gPipeFdWind[0] ? mFdWind : gPipeFdWind[0]) + 1;
    int res;

    mFrameCorrect=false;
    qDebug("BEFORE WHILE"); 
    while(true)
    {
        qDebug("\n IN WHILE LOOP"); 
        usleep(50);
        FD_ZERO(&readfs);
        FD_SET(mFdWind,&readfs);
        FD_SET(gPipeFdWind[0],&readfs);

        res=select(max_fd,&readfs,NULL,NULL,NULL);
        if(res < 0)
            perror("Select Failed");
        else if(res == 0)
            puts("TIMEOUT");
        else
        {
            if(FD_ISSET(mFdWind,&readfs))
            {
                puts("*************** RECEIVED DATA ****************");
                mFrameCorrect=false;
                FlushBuf();
                //int n=mPort->ReadPort(mBuf,100);
                int n=mPort->ReadPort(mBuf,100);

                if(n>0)
                {
                    Count++;


                    QString str((const char*)mBuf);
                    //qDebug("\n %s",qPrintable(str));
                    //See if the Header of the frame is valid
                    if(IsHeaderValid(str))
                    {
                        if( (!IsCommaCountOk(str)) || (!IsChecksumOk(str,mBuf)) ||  (!CalculateCommaIndexes(str))  ) 
                        {

                            qDebug("\n  not ok");
                            mFrameCorrect=false;
                        } //if frame is incorrect
                        else 
                        {
                            qDebug("\n  OK");
                            mFrameCorrect=true;
                        }//if frame is correct(checksum etc are ok)
                    }//else if header is ok
                }//if n > 0
            }//if data received FD_ISSET
            if(FD_ISSET(gPipeFdWind[0],&readfs))
                break;
        }//end nested else res not <= 0
    }//infinite loop  
}

Вышеуказанный поток запускается из основного потока GUI. Это работает нормально. Проблема в том, что я дал пользователю возможность повторной проверки подсистемы по своему усмотрению. Для этого я удаляю экземпляр синглтона, используя

delete SensorClass::instance();

, а затем перезапустите синглтон, используя

SensorClass::instace()->start();

Проблема в том, что на этот раз, когда элемент управления выходит из функции while в run (), сразу после входа в цикл while, я предполагаю, что чтение канала снова считывалось из канала записи, который был записан в последний раз. Я пытался использовать fflush () для очистки ввода / вывода, но не повезло. Мой вопрос

  1. Думал ли я на правильном пути?

  2. Если да, то как мы можем очистить трубы?

  3. Если нет, никто не может подсказать, почему выборочный повторный тест не работает?

Заранее спасибо ..

Ответы [ 4 ]

1 голос
/ 07 декабря 2009

Предположим, что вы создаете этот поток, наследуя его от QThread (который вы не указали). Из документации QThread :: ~ QThread () :

  • Обратите внимание, что удаление объекта QThread не остановит выполнение потока, который он представляет. Удаление работающего QThread (то есть isFinished () возвращает false), вероятно, приведет к сбою программы.

Так что утверждение delete SensorClass::instance();, вероятно, очень, очень плохая идея. В частности, будет сложно разобраться в поведении этой программы с учетом этого недостатка. Прежде чем продолжить, вы можете захотеть найти способ удалить экземпляр и убедиться, что поток тоже исчезнет.

Другая проблема приходит на ум. Когда вы запускаете delete SensorClass::instance(), вы избавляетесь от какого-то объекта (на кучу надеетесь). Кто говорит держателю синглтона, что его объект исчез? Например. чтобы следующий вызов SensorClass::instance() знал, что ему нужно выделить другой экземпляр? Правильно ли это обрабатывается в SensorClass::~SensorClass?

Предположим, это не проблема. Это, вероятно, означает, что указатель на экземпляр содержится в глобальной переменной (или, например, статическом члене уровня класса). Вероятно, это не имеет значения для этой ситуации, но правильно ли синхронизирован доступ к этому члену? То есть есть ли мьютекс, заблокированный для каждого доступа к нему?

1 голос
/ 07 декабря 2009

Вы действительно не хотите запускать инициализацию в потоке. Это проблема номер один, которая значительно усложняет вашу проблему и на которую по какой-то причине никто не указывает.

Просто сделайте инициализацию своей собственной функцией, затем установите переменную защиты и блокировку, и все, что использует ее, отдельно инициализируют ее при запуске.

1 голос
/ 07 декабря 2009

fflush очищает выходной буфер. Если вы хотите очистить входной буфер, вам нужно будет прочитать данные или выполнить поиск до конца.

Я не уверен, что паттерн "Синглтон" подходит. Существуют и другие способы обеспечения не более одного экземпляра для каждого компонента оборудования. Что, если вам понадобятся несколько потоков, каждый из которых будет работать с разным датчиком?

0 голосов
/ 07 декабря 2009

То есть, вы сигнализируете, записывая что-то в канал, и канал создается только один раз, то есть повторно используется в более поздних потоках?

Считайте сигналы вдали от трубы. Предполагая, что вы подаете сигнал, записывая один байт, вместо того, чтобы просто вывести его из строя, вы сделаете что-то вроде (NB, проверка ошибок не приведена ниже):

if(FD_ISSET(gPipeFdWind[0],&readfs)) {  
    char c;  
    read(gPipeFdWind[0], &c, 1);  
    break;  
}

Есть , есть также классы Qt для обработки ввода / вывода через сокет, например, QTcpSocket, который сделает код не только чище, но и кроссплатформенным. Или хотя бы QSocketNotifier для абстрагирования выбора.

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