2023-12-09 12:53:56 +00:00
|
|
|
/***************************************************************************
|
|
|
|
*
|
|
|
|
* main.cpp: Code to solve Barlas Exersice 3-12.
|
|
|
|
*
|
|
|
|
* Version 0.5 by Hartmut Weber: Just a template. 3-11 not solved.
|
2023-12-09 13:00:16 +00:00
|
|
|
* 1.0 by Robin Dietzel: Add QSemaphores to apply rules from 3-11 task
|
2023-12-09 12:53:56 +00:00
|
|
|
*
|
|
|
|
* Statemet of Version 1.0 Authorship:
|
2023-12-09 13:00:16 +00:00
|
|
|
* All added code to the template originates from my own.
|
2023-12-09 12:53:56 +00:00
|
|
|
*
|
|
|
|
**************************************************************************/
|
|
|
|
#include <QCoreApplication>
|
|
|
|
#include <QTimer>
|
|
|
|
#include <QThread>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <QSemaphore>
|
|
|
|
#include <QRandomGenerator>
|
|
|
|
|
|
|
|
using namespace std;
|
|
|
|
|
|
|
|
#define CHAR_COUNT_MAX 500
|
|
|
|
#define TIME_FACTOR 2
|
|
|
|
|
|
|
|
int charCount = 0;
|
|
|
|
QSemaphore semCharCount(1);
|
|
|
|
QRandomGenerator *randg = QRandomGenerator::global();
|
|
|
|
|
|
|
|
QSemaphore lockBC_(0);
|
|
|
|
QSemaphore lockC_(0);
|
|
|
|
|
|
|
|
class AThread : public QThread {
|
|
|
|
private:
|
|
|
|
int ID;
|
|
|
|
public:
|
|
|
|
AThread(int i) : ID(i) {}
|
|
|
|
|
|
|
|
void run() {
|
|
|
|
while (charCount < CHAR_COUNT_MAX) {
|
|
|
|
lockBC_.release(1);
|
|
|
|
printf("A");
|
|
|
|
fflush(stdout);
|
|
|
|
semCharCount.acquire();
|
|
|
|
charCount++;
|
|
|
|
semCharCount.release();
|
|
|
|
msleep((randg->generate() % 3 + 1) * TIME_FACTOR);
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
class BThread : public QThread {
|
|
|
|
private:
|
|
|
|
int ID;
|
|
|
|
public:
|
|
|
|
BThread(int i) : ID(i) {}
|
|
|
|
|
|
|
|
void run() {
|
|
|
|
while (charCount < CHAR_COUNT_MAX) {
|
|
|
|
if (lockBC_.tryAcquire(1)) {
|
|
|
|
if (lockC_.available() == 0) {
|
|
|
|
lockC_.release(1);
|
|
|
|
}
|
|
|
|
printf("B");
|
|
|
|
fflush(stdout);
|
|
|
|
semCharCount.acquire();
|
|
|
|
charCount++;
|
|
|
|
semCharCount.release();
|
|
|
|
};
|
|
|
|
msleep((randg->generate() % 3 + 1) * TIME_FACTOR);
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
class CThread : public QThread {
|
|
|
|
private:
|
|
|
|
int ID;
|
|
|
|
public:
|
|
|
|
CThread(int i) : ID(i) {}
|
|
|
|
|
|
|
|
void run() {
|
|
|
|
while (charCount < CHAR_COUNT_MAX) {
|
|
|
|
if (lockC_.tryAcquire(1) && lockBC_.tryAcquire(1)) {
|
|
|
|
printf("C");
|
|
|
|
fflush(stdout);
|
|
|
|
semCharCount.acquire();
|
|
|
|
charCount++;
|
|
|
|
semCharCount.release();
|
|
|
|
}
|
|
|
|
msleep((randg->generate() % 3 + 1) * TIME_FACTOR);
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
int main(int argc, char *argv[]) {
|
|
|
|
QCoreApplication a(argc, argv);
|
|
|
|
|
|
|
|
printf("START\n\n");
|
|
|
|
fflush(stdout);
|
|
|
|
AThread *pTa = new AThread(1);
|
|
|
|
BThread *pTb = new BThread(2);
|
|
|
|
CThread *pTc = new CThread(3);
|
|
|
|
|
|
|
|
pTa->start();
|
|
|
|
pTb->start();
|
|
|
|
pTc->start();
|
|
|
|
|
|
|
|
pTa->wait();
|
|
|
|
pTb->wait();
|
|
|
|
pTc->wait();
|
|
|
|
printf("\n\n");
|
|
|
|
fflush(stdout);
|
|
|
|
|
|
|
|
// Let event loop do at least one turn. (https:/stackoverflow.com/questions/4180394)
|
|
|
|
QTimer::singleShot(0, &a, &QCoreApplication::quit); // Let event loop do at least one turn.
|
|
|
|
|
|
|
|
return a.exec();
|
|
|
|
}
|