Russian Qt Forum

Qt => Многопоточное программирование, процессы => Тема начата: RedDog от Февраль 02, 2012, 08:40



Название: Не перезапускать поток
Отправлено: RedDog от Февраль 02, 2012, 08:40
Как сделать нечто подобное:

Код
C++ (Qt)
class Searcher;
class MyThread : public QThread
{
private:
   Searcher *_searcher;
   void *pBuf;
   qint64 bufSize;
   bool stop;
public:
   void run();
   void setScanBuf(void *buf, qint64 size)
   {
        pBuf = buf;
        bufSize = size;
   }
};
 
Код
C++ (Qt)
void MyThread::run()
{
   while (!stop)
   {
        bool found = _searcher->Search(pBuf, bufSize);
        emit result(found);
        waitForSomeMutex(someMutex);
   }
}

т.е. создается класс потока, в него передается указатель на буфер для поиска, запускается поток, которй что то ищет.
Буферов, в которых надо искать очень много, и что бы избежать оверхеда при перезапуске потоков (их  >1 будет) надо
дождаться некоего сигнала из главного потока, что буфер сменен и можно продолжать дальше уже с новым буфером.
Т.е. через чего лучше организовать waitForSomeMutex(someMutex) ?


Название: Re: Не перезапускать поток
Отправлено: alexman от Февраль 02, 2012, 08:55
Можно, через QEventLoop попробовать.


Название: Re: Не перезапускать поток
Отправлено: RedDog от Февраль 02, 2012, 09:01
Это как? Ни разу с ним не работал, плохо представляю.


Название: Re: Не перезапускать поток
Отправлено: alexman от Февраль 02, 2012, 09:09
Да сам не пробовал. Главное выяснить: не будет ли грузить процессор int QEventLoop::exec ( ProcessEventsFlags flags = AllEvents ).

Код:
class Searcher;
class MyThread : public QThread
{
     Q_OBJECT
    
private:
    QEventLoop *_eventLoop;
    Searcher *_searcher;
    void *pBuf;
    qint64 bufSize;
    bool stop;

public:
    void run();
    void setScanBuf(void *buf, qint64 size)
    {
         pBuf = buf;
         bufSize = size;
    }

    void seach()
    {
          emit exitLoop();
    }

signals:
    void exitLoop();
};

Код:
void MyThread::run()
{
    QEventLoop eventLoop;
    connect(this, SIGNAL(exitLoop()), &eventLoop, SLOT(quit()), Qt::QueuedConnection);

    while (!stop)
    {
         eventLoop.exec();

         bool found = _searcher->Search(pBuf, bufSize);
         emit result(found);
    }
}

UPDATE: RedDog, немного поправил. Должно работать.


Название: Re: Не перезапускать поток
Отправлено: alexman от Февраль 02, 2012, 09:10
Еще не забудь, что, возможно, некоторые данные надо мьютексом закрыть.


Название: Re: Не перезапускать поток
Отправлено: Igors от Февраль 02, 2012, 09:42
Код
C++ (Qt)
void MyThread::run()
{
   while (true)
   {
        void * pBuf;
        qint64 bufSize;
        mSemaphore.acquire();   // ждем на семафоре если нет буферов
        if (stop) return;
        else {
         QMutexLocker locker(&theBufMuteх);    // захватываем контейнер буферов
         pBuf = GetBuf(&bufSize);             // извлекаем буфер из контейнера (takeAt)
         if (!pBuf) continue;                 // подстраховались
         if (pBuf == theEndOfJob) return;      // часто так лучше чем stop
        }
        bool found = _searcher->Search(pBuf, bufSize);
        emit result(found);
   }
}



Название: Re: Не перезапускать поток
Отправлено: RedDog от Февраль 02, 2012, 13:11
alexman, не до конца понял...
главный поток работает по принципу:
Код:
for (int i = 0; i < threadCount; ++i)
_treads[i]->start();
после того как все отработали (счетчик стоит автодекрементый на сигнал found(bool)), тормозим все и запускаем заново:
Код:
for (int i = 0; i < threadCount; ++i)
{
   _treads[i]->exit(0);
   _treads[i]->wait();
   _treads[i]->setScanBuf(pBuf, bufSize);
   _treads[i]->start();
}
тогда с QEventLoop получается следующее:

Код:
for (int i = 0; i < threadCount; ++i)
{
//   _treads[i]->exit(0); <== выкидываем
//  _treads[i]->wait(); <== выкидываем
   _treads[i]->setScanBuf(pBuf, bufSize);
   _treads[i]->seach(); << == добавляем
//   _treads[i]->start(); <== выкидываем
}
я идею правильно понял?


Название: Re: Не перезапускать поток
Отправлено: alexman от Февраль 02, 2012, 14:51
Похоже...надо додумывать/пробовать. Только учти, что если exec еще не вызван, но вызван quit() - то в дальнейшем поток может зависнуть.


Название: Re: Не перезапускать поток
Отправлено: RedDog от Февраль 02, 2012, 15:57
Да, так работает, только
Код:
eventLoop.exec();
перенес в конец цикла, иначе на нем все останавливается.
Хотя выгоды получил от этого всего %10 по скорости. Но зато проц не так сильно жрет теперь.
Мутексы не быстрее работать будут?


Название: Re: Не перезапускать поток
Отправлено: alexman от Февраль 02, 2012, 16:10
Хотя выгоды получил от этого всего %10 по скорости.
Имеешь в виду прирост скорости от использования потоков?


Название: Re: Не перезапускать поток
Отправлено: RedDog от Февраль 02, 2012, 16:32
Имеешь в виду прирост скорости от использования потоков?
нет, имел ввиду прирост скорости без перезапуска потоков.