#include #include #include #include struct IPrintable { ~IPrintable() = default; virtual auto print() const -> void = 0; }; class PrintA : public IPrintable { private: QSemaphore &lockBC_; public: explicit PrintA(QSemaphore &lockBc) : lockBC_(lockBc) {} auto print() const -> void override { this->lockBC_.release(1); std::cout << "A"; } }; class PrintB : public IPrintable { private: QSemaphore &lockBC_; QSemaphore &lockC_; public: explicit PrintB(QSemaphore &lockBc, QSemaphore &lockC) : lockBC_(lockBc), lockC_(lockC) {} auto print() const -> void override { if (this->lockBC_.tryAcquire(1)) { if (this->lockC_.available() == 0) { this->lockC_.release(1); } std::cout << "B"; } } }; class PrintC : public IPrintable { private: QSemaphore &lockBC_; QSemaphore &lockC_; public: explicit PrintC(QSemaphore &lockBc, QSemaphore &lockC) : lockBC_(lockBc), lockC_(lockC) {} auto print() const -> void override { if (this->lockBC_.tryAcquire(1)) { if (this->lockC_.tryAcquire(1)) { std::cout << "C"; } else { this->lockBC_.release(1); } } } }; template class Worker : public QThread { private: std::unique_ptr printer_; public: template Worker(QString tname, Argts &... args) : printer_(std::make_unique(args...)) {}; protected: void run() { while (true) { printer_->print(); std::cout.flush(); sleep(1); } } }; int main(int argc, char *argv[]) { QSemaphore lockC(1); QSemaphore lockBC(0); Worker t1("Thread 1", lockBC); Worker t2("Thread 1", lockBC, lockC); Worker t3("Thread 1", lockBC, lockC); t1.start(); t2.start(); t3.start(); t1.wait(); t2.wait(); t3.wait(); return 0; }