2016-11-08 3 views
0

Я использую QSharedMemory и QSystemSemaphore для организации обмена событиями между несколькими процессами. QSharedMemory хранит количество приемников и данных событий. Приемники ждут в QSystemSemaphore :: приобретают(). Отправитель уведомляет их через QSystemSemaphore :: release ([количество приемников]).QSystemSemaphore :: приобретать() abort

Есть ли способ прекратить процесс приемника изящно за исключением введения флага «реальный»/«поддельный» в общей памяти и последующего генерирования «поддельного» события в процессе завершения?

+0

вы quesiton неясны сформулированы. Вы имеете в виду, когда вы вызываете 'terminate' в потоке, поток ничем не задумывается и застрял в' QSystemSemaphore :: приобретать() '? – Hayt

+0

Это проблема XY: вы должны позволить нам увидеть лес, а не отдельные деревья. Что именно вы делаете? Скорее всего, есть гораздо более простое решение вашей проблемы - какова бы ни была эта проблема. Измените вопрос, чтобы уточнить структуру вашей системы, возможно, создав короткий тестовый пример. Вы можете легко запускать несколько процессов из одного 'main.cpp'! (Http://stackoverflow.com/a/18602568/1329652). –

ответ

2

QThread::terminate() работает на каждой платформе, независимо от того, что делает поток в данный момент. Конечно, когда вы закончили нитью в приложении, единственное, что вы можете с уверенностью сказать, это позвонить abort: процесс в целом в этом состоянии. Не делать делать что-либо кроме abort() -ing после того как вы звоните QThread::terminate. Поскольку это настолько разрушительно, вы можете также отказаться от вызова terminate и прервать его напрямую.

Ваш вопрос сформулирован так, как если бы вы планировали продолжить работу с приложением terminate. Ты не должен!

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

// https://github.com/KubaO/stackoverflown/tree/master/questions/semaphore-quit-40488523 
#include <QtCore> 

class Worker : public QRunnable { 
    static const QString m_key; 
    static QAtomicInteger<bool> m_abort; 
    void run() override { 
     QSystemSemaphore sem{m_key}; 
     qDebug() << "working"; 
     while (true) { 
      sem.acquire(); 
      if (m_abort.load()) { 
       sem.release(); 
       qDebug() << "aborting"; 
       return; 
      } 
      sem.release(); 
     } 
    } 
public: 
    static void acquire(int n = 1) { 
     QSystemSemaphore sem{m_key}; 
     while (n--) 
      sem.acquire(); 
    } 
    static void release(int n = 1) { 
     QSystemSemaphore{m_key}.release(n); 
    } 
    static void quit(int n) { 
     m_abort.store(true); 
     release(n); 
    } 
}; 
const QString Worker::m_key = QStringLiteral("semaphore-quit-40488523"); 
QAtomicInteger<bool> Worker::m_abort = false; 

int main() 
{ 
    QThreadPool pool; 
    QVarLengthArray<Worker, 20> workers{20}; 
    for (auto & worker : workers) { 
     worker.setAutoDelete(false); 
     pool.start(&worker); 
    } 
    Worker::release(workers.size()); // get some workers churning 
    QThread::sleep(5); 
    Worker::acquire(workers.size()); // pause all the workers 
    Worker::quit(workers.size()); 
    // The thread pool destructor will wait for all workers to quit. 
} 
+0

ОК, я имею в виду, что QThread :: wait() после того, как QThread :: terminate() работает (успешно завершен) в Windows, но не в Linux. И я согласен, что terminate() - это плохой способ, но каковы альтернативы? Вопрос не в terminate(). Речь идет о том, как прервать получение(). – groaner

+0

@groaner Опять же, ** только ** вещь, которую вы можете сделать после 'QThread :: terminate'' 'abort()'. То, что он работает на Windows, является совпадением. Он не должен работать, и он не гарантированно работает, и, конечно же, Linux не работает. Альтернативой является «освобождение» семафора ... это ваш семафор, верно? Вы должны делать что-то странное. Покажите свой код. –

+0

Это не мой (inprocess) семафор. Это глобальный (межпроцессный) семафор (QSystemSemaphore, а не QSemaphore). Я использую его для доставки событий от одного процесса к другому. Если я выпущу его в один процесс, это может повлиять на другие, не так ли? – groaner

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