2010-05-26 2 views
1

Я хочу реализовать многопоточную среду с использованием Qt4. Идея заключается в том, как следует в C++ -, так псевдокод:Внедрение многопоточной среды

class Thread : public QThread { 
    QList<SubThread*> threads_; 

public: 
    void run() { 
     foreach(SubThread* thread : threads) { 
      thread.start(); 
     } 

     foreach(SubThread* thread : threads) { 
      thread.wait(); 
     } 
    } 

    void abort() { 
     foreach(SubThread* thread : threads) { 
      thread.cancel(); 
     } 
    } 

public slots: 
    // This method is called from the main-thread 
    // (sometimes via some signal-slot-connection) 
    void changeSomeSettings() { 
     abort(); 
     // change settings 
     start(); 
    } 
} 

class SubThread : public QThread { 
    bool isCancelled_; 

public: 
    void run() { 
     while(!isCancelled or task completed) { 
      // something that takes some time... 
     } 
    } 

    void cancel() { 
     if(isRunning() { 
      isCancelled_ = true; 
     } 
    } 
} 

Цель состоит в том, что слот changeSomeSettings() убивает все запущенные потоки, совершают свои изменения и перезапускает его. То, что я хочу достичь, заключается в том, что как только этот метод был запущен, он вызывает «прервать», а затем ждет, пока все потоки не прекратятся. Использование семафоров в неправильном направлении:

void Thread::changeSomeSettings() { 
     mutex1.lock(); 
     abort(); 

     mutex2.lock(); 

     start(); 
     mutex1.unlock(); 
    } 

    void Thread::run() { 
     foreach(Thread* thread : threads) { 
      thread.start(); 
     } 

     foreach(Thread* thread : threads) { 
      thread.wait(); 
     } 

     mutex2.unlock(); 
    } 

Это на самом деле работает в Qt под MacOSX, но в соответствии с документацией mutex2 должны быть разблокированы в том же потоке (и в Windows, я получаю сообщение об ошибке). Каков наилучший способ достичь моей цели, не вбегая в гоночные условия и тупики? Есть ли лучший дизайн, чем тот, который я предложил здесь?

ответ

2

Возможно, вы захотите использовать переменную условия вместо мьютекса для этой ситуации. Переменная состояния - это способ, которым один поток сигнализирует другой. Реализация QT представляется QTWaitCondition:

У меня может быть дочерний поток, периодически проверяющий состояние переменной условия. Это можно сделать с помощью QTWaitCondition :: wait() с коротким/0 таймаутом. Если это сигнализируется, заблокируйте область общей памяти, содержащую обновленные данные, и получите доступ к данным, которые необходимо обновить. Затем этот поток может безопасно перезапустить его соответствующим образом.

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

+0

Спасибо за подсказку с условиями QWaitConditions. – Searles

Смежные вопросы