Fix prod con example
This commit is contained in:
parent
5e7049feb0
commit
fa11a8d942
@ -1,24 +0,0 @@
|
|||||||
cmake_minimum_required(VERSION 3.14)
|
|
||||||
|
|
||||||
project(BarlasChpt3Ex12 LANGUAGES CXX)
|
|
||||||
|
|
||||||
set(CMAKE_AUTOUIC ON)
|
|
||||||
set(CMAKE_AUTOMOC ON)
|
|
||||||
set(CMAKE_AUTORCC ON)
|
|
||||||
|
|
||||||
set(CMAKE_CXX_STANDARD 17)
|
|
||||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
|
||||||
|
|
||||||
find_package(QT NAMES Qt6 Qt5 REQUIRED COMPONENTS Core)
|
|
||||||
find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Core)
|
|
||||||
|
|
||||||
add_executable(BarlasChpt3Ex12
|
|
||||||
main.cpp
|
|
||||||
)
|
|
||||||
target_link_libraries(BarlasChpt3Ex12 Qt${QT_VERSION_MAJOR}::Core)
|
|
||||||
|
|
||||||
include(GNUInstallDirs)
|
|
||||||
install(TARGETS BarlasChpt3Ex12
|
|
||||||
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
|
||||||
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
|
||||||
)
|
|
@ -1,86 +0,0 @@
|
|||||||
#include <iostream>
|
|
||||||
#include <QSemaphore>
|
|
||||||
#include <QThread>
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Barlas Chpt 3 Ex 12:
|
|
||||||
Create three threads, each printing out the letters A, B, and C.
|
|
||||||
The printing must adhere to these rules:
|
|
||||||
• The total number of Bs and Cs that have been output at any
|
|
||||||
point in the output string cannot exceed the total number
|
|
||||||
of As that have been output at that point.
|
|
||||||
• After a C has been output, another C cannot be output until
|
|
||||||
one or more Bs have been output.
|
|
||||||
Use semaphores to solve the problem.
|
|
||||||
*/
|
|
||||||
|
|
||||||
class printer{
|
|
||||||
private:
|
|
||||||
QSemaphore* lockBC;
|
|
||||||
QSemaphore* lockC;
|
|
||||||
|
|
||||||
public:
|
|
||||||
printer(QSemaphore* lockBC, QSemaphore* lockC){
|
|
||||||
this->lockBC = lockBC;
|
|
||||||
this->lockC = lockC;
|
|
||||||
}
|
|
||||||
|
|
||||||
void printA(){
|
|
||||||
this->lockBC->release(1);
|
|
||||||
std::cout << "A\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
void printB(){
|
|
||||||
if(this->lockBC->tryAcquire(1)){
|
|
||||||
if(this->lockC->available() == 0){
|
|
||||||
this->lockC->release(1);
|
|
||||||
}
|
|
||||||
std::cout << "B\n";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void printC(){
|
|
||||||
if(this->lockBC->tryAcquire(1)){
|
|
||||||
if(this->lockC->tryAcquire(1)){
|
|
||||||
std::cout << "C\n";
|
|
||||||
}else{
|
|
||||||
this->lockBC->release(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
class worker : public QThread{
|
|
||||||
private:
|
|
||||||
QSemaphore* lockBC;
|
|
||||||
QSemaphore* lockC;
|
|
||||||
|
|
||||||
public:
|
|
||||||
worker(QSemaphore* lockBC, QSemaphore* lockC){
|
|
||||||
this->lockBC = lockBC;
|
|
||||||
this->lockC = lockC;
|
|
||||||
}
|
|
||||||
|
|
||||||
void run(){
|
|
||||||
printer print = printer(this->lockBC, this->lockC);
|
|
||||||
print.printA();
|
|
||||||
print.printB();
|
|
||||||
print.printC();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
|
||||||
{
|
|
||||||
QSemaphore lockC(1);
|
|
||||||
QSemaphore lockBC(0);
|
|
||||||
|
|
||||||
int N = 3;
|
|
||||||
worker *workers[N];
|
|
||||||
for(int i = 0; i < N; i++){
|
|
||||||
workers[i] = new worker(&lockBC, &lockC);
|
|
||||||
workers[i]->run();
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
@ -27,3 +27,4 @@ add_subdirectory(third-party/fmt)
|
|||||||
# Include CMakeLists files from subdirs for specific tasks
|
# Include CMakeLists files from subdirs for specific tasks
|
||||||
add_subdirectory(task1)
|
add_subdirectory(task1)
|
||||||
add_subdirectory(task3)
|
add_subdirectory(task3)
|
||||||
|
add_subdirectory(task4)
|
@ -1,27 +0,0 @@
|
|||||||
cmake_minimum_required(VERSION 3.14)
|
|
||||||
|
|
||||||
project(MonitorExample LANGUAGES CXX)
|
|
||||||
|
|
||||||
set(CMAKE_AUTOUIC ON)
|
|
||||||
set(CMAKE_AUTOMOC ON)
|
|
||||||
set(CMAKE_AUTORCC ON)
|
|
||||||
|
|
||||||
set(CMAKE_CXX_STANDARD 17)
|
|
||||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
|
||||||
|
|
||||||
find_package(QT NAMES Qt6 Qt5 REQUIRED COMPONENTS Core)
|
|
||||||
find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Core)
|
|
||||||
|
|
||||||
add_executable(MonitorExample
|
|
||||||
main.cpp
|
|
||||||
monitor.h monitor.cpp
|
|
||||||
producer.h producer.cpp
|
|
||||||
consumer.h consumer.cpp
|
|
||||||
)
|
|
||||||
target_link_libraries(MonitorExample Qt${QT_VERSION_MAJOR}::Core)
|
|
||||||
|
|
||||||
include(GNUInstallDirs)
|
|
||||||
install(TARGETS MonitorExample
|
|
||||||
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
|
||||||
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
|
||||||
)
|
|
@ -1,26 +0,0 @@
|
|||||||
#include "consumer.h"
|
|
||||||
|
|
||||||
template<typename T> QSemaphore Consumer<T>::numProducts;
|
|
||||||
template<typename T> Monitor<T> *Consumer<T>::mon;
|
|
||||||
template<> void (*Consumer<int>::consume)(int, int) = NULL;
|
|
||||||
|
|
||||||
//---------------------------------------
|
|
||||||
template<typename T> void Consumer<T>::initClass(int numP, Monitor<T> *m, void (*cons)(T, int)) {
|
|
||||||
numProducts.release(numP);
|
|
||||||
mon = m;
|
|
||||||
consume = cons;
|
|
||||||
}
|
|
||||||
//---------------------------------------
|
|
||||||
|
|
||||||
//Semaphore with Number of Resources -> consume N Resources
|
|
||||||
//get spot of item in queue, take item, activate producers
|
|
||||||
//process item
|
|
||||||
template<typename T> void Consumer<T>::run() {
|
|
||||||
while (numProducts.tryAcquire()) { // While not all numProducts are consumed:
|
|
||||||
T* aux = mon->canGet(); // Get pointer to item in itemQ
|
|
||||||
T item = *aux; // Take the item out of itemQ
|
|
||||||
mon->doneGetting(aux); // Give info to producer threads
|
|
||||||
(*consume)(item,ID); // Consume one item
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//---------------------------------------
|
|
@ -1,22 +0,0 @@
|
|||||||
#ifndef CONSUMER_H
|
|
||||||
#define CONSUMER_H
|
|
||||||
|
|
||||||
#include "monitor.h"
|
|
||||||
#include <QThread>
|
|
||||||
#include <QSemaphore>
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
class Consumer : public QThread {
|
|
||||||
private:
|
|
||||||
int ID;
|
|
||||||
static Monitor<T> *mon;
|
|
||||||
static QSemaphore numProducts;
|
|
||||||
public:
|
|
||||||
static void (*consume)(T i, int);
|
|
||||||
static void initClass(int numP, Monitor<T> *m, void (*cons)(T, int));
|
|
||||||
|
|
||||||
Consumer<T>(int i) : ID(i) {}
|
|
||||||
void run();
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // CONSUMER_H
|
|
@ -1,69 +0,0 @@
|
|||||||
#include "monitor.h"
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
Monitor<T>::Monitor(int n) {
|
|
||||||
buffer = new T[n];
|
|
||||||
for(int i=0;i<n;i++)
|
|
||||||
emptySpotsQ.push(&buffer[i]); // Initialize emptySpotsQ with buffer places
|
|
||||||
}
|
|
||||||
//-----------------------------------------
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
Monitor<T>::~Monitor() {
|
|
||||||
delete []buffer;
|
|
||||||
}
|
|
||||||
//-----------------------------------------
|
|
||||||
|
|
||||||
//producer tries to put an item:
|
|
||||||
// lock l
|
|
||||||
// wait for spot in putting queue
|
|
||||||
// get first spot in putting queue
|
|
||||||
template<typename T>
|
|
||||||
T* Monitor<T>::canPut() {
|
|
||||||
QMutexLocker ml(&l); // Lock entry controlling mutex l
|
|
||||||
while (emptySpotsQ.size() == 0) // If no free place in emptySpots queue:
|
|
||||||
full.wait(&l); // Block until condition variable full is given free by mutex l
|
|
||||||
T *aux = emptySpotsQ.front(); // Get place in emptySpotsQ
|
|
||||||
emptySpotsQ.pop(); // ?? Free one place in emptySpotsQ ?? (documentation of class queue currently not available)
|
|
||||||
return aux; // Return pointer to place in emptySpotsQ for item to be produced
|
|
||||||
}
|
|
||||||
//-----------------------------------------
|
|
||||||
|
|
||||||
//consumer tries to take an item:
|
|
||||||
// lock l
|
|
||||||
// wait until items are in itemq
|
|
||||||
// take item
|
|
||||||
template<typename T>
|
|
||||||
T* Monitor<T>::canGet() {
|
|
||||||
QMutexLocker ml(&l); // Lock entry controlling mutex l
|
|
||||||
while (itemQ.size() == 0) // If no item in itemQ:
|
|
||||||
empty.wait(&l); // Block until condition variable empty is given free by mutex l
|
|
||||||
T* temp = itemQ.front(); // Get item out of itemQ
|
|
||||||
itemQ.pop(); // ?? Free one place in itemQ ?? (documentation of class queue currently not available)
|
|
||||||
return temp; // Return pointer to item in itemQ, which will be consumed
|
|
||||||
}
|
|
||||||
//-----------------------------------------
|
|
||||||
|
|
||||||
//producer is done with producing and wants to put that item:
|
|
||||||
// lock l
|
|
||||||
// push produced item to itemQ
|
|
||||||
// wake waiting consumer
|
|
||||||
template<typename T>
|
|
||||||
void Monitor<T>::donePutting(T *x) {
|
|
||||||
QMutexLocker ml(&l); // Lock entry controlling mutex l
|
|
||||||
itemQ.push(x); // Push place with produced item into itemQ
|
|
||||||
empty.wakeOne(); // Notify one consumer thread waiting for condition variable empty
|
|
||||||
}
|
|
||||||
//-----------------------------------------
|
|
||||||
|
|
||||||
//consumer is done with taking an item:
|
|
||||||
// lock l
|
|
||||||
// enlarge producer queue by one
|
|
||||||
// notify a producer of new spot
|
|
||||||
template<typename T>
|
|
||||||
void Monitor<T>::doneGetting(T *x) {
|
|
||||||
QMutexLocker ml(&l); // Lock entry controlling mutex l
|
|
||||||
emptySpotsQ.push(x); // Give free the buffer place which had hold the consumed item by pushing in into emptySpotsQ
|
|
||||||
full.wakeOne(); // Notify one producer thread waiting for condition variable empty
|
|
||||||
}
|
|
||||||
//************************************************************
|
|
@ -1,31 +0,0 @@
|
|||||||
#ifndef MONITOR_H
|
|
||||||
#define MONITOR_H
|
|
||||||
#include <QMutexLocker>
|
|
||||||
#include <QWaitCondition>
|
|
||||||
#include <queue>
|
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
const int BUFFSIZE = 100;
|
|
||||||
//************************************************************
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
class Monitor {
|
|
||||||
private:
|
|
||||||
QMutex l;
|
|
||||||
QWaitCondition full, empty; // full: Condition variable for queue itemQ.
|
|
||||||
// empty: Condition variable for queue emptySpotsQ.
|
|
||||||
|
|
||||||
queue<T *> emptySpotsQ; // Queue of free item buffer places for items to be produced
|
|
||||||
queue<T *> itemQ; // Queue of item buffer places with items to be consumed
|
|
||||||
T *buffer; // Item buffer
|
|
||||||
public:
|
|
||||||
T* canPut();
|
|
||||||
T* canGet();
|
|
||||||
void donePutting(T *x);
|
|
||||||
void doneGetting(T *x);
|
|
||||||
Monitor(int n = BUFFSIZE);
|
|
||||||
~Monitor();
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // MONITOR_H
|
|
@ -1,28 +0,0 @@
|
|||||||
#include "producer.h"
|
|
||||||
|
|
||||||
//---------------------------------------
|
|
||||||
template<typename T> QSemaphore Producer<T>::numProducts;
|
|
||||||
template<typename T> Monitor<T> * Producer<T>::mon;
|
|
||||||
template<> int (*Producer<int>::produce)(int) = NULL;
|
|
||||||
//---------------------------------------
|
|
||||||
|
|
||||||
template<typename T> void Producer<T>::initClass(int numP, Monitor<T> *m, T(*prod)(int)) {
|
|
||||||
mon = m;
|
|
||||||
numProducts.release(numP);
|
|
||||||
produce = prod;
|
|
||||||
}
|
|
||||||
//---------------------------------------
|
|
||||||
|
|
||||||
//Semaphore with Number of Resources -> create N Resources
|
|
||||||
//produce item -> get spot in queue -> put item into second queue
|
|
||||||
//activate consumers
|
|
||||||
template<typename T>
|
|
||||||
void Producer<T>::run() {
|
|
||||||
while (numProducts.tryAcquire()) { // While not all numProducts items are produced:
|
|
||||||
T item = (*produce)(ID); // Produce one item
|
|
||||||
T* aux = mon->canPut(); // Get place for item in emptySpotsQ
|
|
||||||
*aux = item; // Put item into emptySpotsQ
|
|
||||||
mon->donePutting(aux); // Give info to consumer threads
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//---------------------------------------
|
|
@ -1,21 +0,0 @@
|
|||||||
#ifndef PRODUCER_H
|
|
||||||
#define PRODUCER_H
|
|
||||||
#include "monitor.h"
|
|
||||||
#include <QThread>
|
|
||||||
#include <QSemaphore>
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
class Producer : public QThread {
|
|
||||||
private:
|
|
||||||
static QSemaphore numProducts;
|
|
||||||
int ID;
|
|
||||||
static Monitor<T> *mon;
|
|
||||||
public:
|
|
||||||
static T(*produce)(int);
|
|
||||||
static void initClass(int numP, Monitor<T> *m, T(*prod)(int));
|
|
||||||
|
|
||||||
Producer<T>(int i) : ID(i) {}
|
|
||||||
void run();
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // PRODUCER_H
|
|
@ -2,7 +2,9 @@
|
|||||||
find_package(Qt6 COMPONENTS Core REQUIRED)
|
find_package(Qt6 COMPONENTS Core REQUIRED)
|
||||||
|
|
||||||
add_executable(task3-chpt3ex12)
|
add_executable(task3-chpt3ex12)
|
||||||
|
|
||||||
target_sources(task3-chpt3ex12 PRIVATE
|
target_sources(task3-chpt3ex12 PRIVATE
|
||||||
main.cpp)
|
main.cpp)
|
||||||
|
|
||||||
target_link_libraries(task3-chpt3ex12 PRIVATE
|
target_link_libraries(task3-chpt3ex12 PRIVATE
|
||||||
Qt6::Core)
|
Qt6::Core)
|
14
task4/CMakeLists.txt
Normal file
14
task4/CMakeLists.txt
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
find_package(Qt6 COMPONENTS Core REQUIRED)
|
||||||
|
|
||||||
|
add_executable(task4-monitor)
|
||||||
|
|
||||||
|
target_include_directories(task4-monitor PRIVATE
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/include)
|
||||||
|
|
||||||
|
target_sources(task4-monitor PRIVATE
|
||||||
|
src/main.cpp
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
target_link_libraries(task4-monitor PRIVATE
|
||||||
|
Qt6::Core)
|
36
task4/include/consumer.h
Normal file
36
task4/include/consumer.h
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "monitor.h"
|
||||||
|
#include <QThread>
|
||||||
|
#include <QSemaphore>
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
class Consumer : public QThread {
|
||||||
|
private:
|
||||||
|
int ID;
|
||||||
|
static Monitor<T> *mon;
|
||||||
|
static QSemaphore numProducts;
|
||||||
|
public:
|
||||||
|
static void (*consume)(T i, int);
|
||||||
|
|
||||||
|
static void initClass(int numP, Monitor<T> *m, void (*cons)(T, int)) {
|
||||||
|
numProducts.release(numP);
|
||||||
|
mon = m;
|
||||||
|
consume = cons;
|
||||||
|
};
|
||||||
|
|
||||||
|
Consumer(int i) : ID(i) {};
|
||||||
|
|
||||||
|
void run() {
|
||||||
|
while (numProducts.tryAcquire()) { // While not all numProducts are consumed:
|
||||||
|
T* aux = mon->canGet(); // Get pointer to item in itemQ
|
||||||
|
T item = *aux; // Take the item out of itemQ
|
||||||
|
mon->doneGetting(aux); // Give info to producer threads
|
||||||
|
(*consume)(item,ID); // Consume one item
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T> QSemaphore Consumer<T>::numProducts;
|
||||||
|
template<typename T> Monitor<T> *Consumer<T>::mon;
|
||||||
|
template<> void (*Consumer<int>::consume)(int, int) = NULL;
|
67
task4/include/monitor.h
Normal file
67
task4/include/monitor.h
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <QMutexLocker>
|
||||||
|
#include <QWaitCondition>
|
||||||
|
#include <queue>
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
const int BUFFSIZE = 100;
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
class Monitor {
|
||||||
|
private:
|
||||||
|
QMutex l;
|
||||||
|
QWaitCondition full, empty;
|
||||||
|
// full: Condition variable for queue itemQ.
|
||||||
|
// empty: Condition variable for queue emptySpotsQ.
|
||||||
|
|
||||||
|
queue<T *> emptySpotsQ; // Queue of free item buffer places for items to be produced
|
||||||
|
queue<T *> itemQ; // Queue of item buffer places with items to be consumed
|
||||||
|
T *buffer; // Item buffer
|
||||||
|
public:
|
||||||
|
T *canPut() {
|
||||||
|
QMutexLocker ml(&l); // Lock entry controlling mutex l
|
||||||
|
while (emptySpotsQ.size() == 0) // If no free place in emptySpots queue:
|
||||||
|
full.wait(&l); // Block until condition variable full is given free by mutex l
|
||||||
|
T *aux = emptySpotsQ.front(); // Get place in emptySpotsQ
|
||||||
|
emptySpotsQ.pop(); // ?? Free one place in emptySpotsQ ?? (documentation of class queue currently not available)
|
||||||
|
return aux; // Return pointer to place in emptySpotsQ for item to be produced
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
T *canGet() {
|
||||||
|
QMutexLocker ml(&l); // Lock entry controlling mutex l
|
||||||
|
while (itemQ.size() == 0) // If no item in itemQ:
|
||||||
|
empty.wait(&l); // Block until condition variable empty is given free by mutex l
|
||||||
|
T *temp = itemQ.front(); // Get item out of itemQ
|
||||||
|
itemQ.pop(); // ?? Free one place in itemQ ?? (documentation of class queue currently not available)
|
||||||
|
return temp; // Return pointer to item in itemQ, which will be consumed
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
void donePutting(T *x) {
|
||||||
|
QMutexLocker ml(&l); // Lock entry controlling mutex l
|
||||||
|
itemQ.push(x); // Push place with produced item into itemQ
|
||||||
|
empty.wakeOne(); // Notify one consumer thread waiting for condition variable empty
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
void doneGetting(T *x) {
|
||||||
|
QMutexLocker ml(&l); // Lock entry controlling mutex l
|
||||||
|
emptySpotsQ.push(
|
||||||
|
x); // Give free the buffer place which had hold the consumed item by pushing in into emptySpotsQ
|
||||||
|
full.wakeOne(); // Notify one producer thread waiting for condition variable empty
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
Monitor(int n = BUFFSIZE) {
|
||||||
|
buffer = new T[n];
|
||||||
|
for (int i = 0; i < n; i++)
|
||||||
|
emptySpotsQ.push(&buffer[i]);
|
||||||
|
};
|
||||||
|
|
||||||
|
~Monitor() {
|
||||||
|
delete[]buffer;
|
||||||
|
};
|
||||||
|
};
|
38
task4/include/producer.h
Normal file
38
task4/include/producer.h
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "monitor.h"
|
||||||
|
#include <QThread>
|
||||||
|
#include <QSemaphore>
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
class Producer : public QThread {
|
||||||
|
private:
|
||||||
|
static QSemaphore numProducts;
|
||||||
|
int ID;
|
||||||
|
static Monitor<T> *mon;
|
||||||
|
public:
|
||||||
|
static T (*produce)(int);
|
||||||
|
|
||||||
|
static void initClass(int numP, Monitor<T> *m, T(*prod)(int)) {
|
||||||
|
mon = m;
|
||||||
|
numProducts.release(numP);
|
||||||
|
produce = prod;
|
||||||
|
};
|
||||||
|
|
||||||
|
Producer(int i) : ID(i) {};
|
||||||
|
|
||||||
|
Producer(QObject *parent, int id);
|
||||||
|
|
||||||
|
void run() {
|
||||||
|
while (numProducts.tryAcquire()) { // While not all numProducts items are produced:
|
||||||
|
T item = (*produce)(ID); // Produce one item
|
||||||
|
T *aux = mon->canPut(); // Get place for item in emptySpotsQ
|
||||||
|
*aux = item; // Put item into emptySpotsQ
|
||||||
|
mon->donePutting(aux); // Give info to consumer threads
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T> QSemaphore Producer<T>::numProducts;
|
||||||
|
template<typename T> Monitor<T> * Producer<T>::mon;
|
||||||
|
template<> int (*Producer<int>::produce)(int) = NULL;
|
@ -1,14 +1,3 @@
|
|||||||
/*
|
|
||||||
============================================================================
|
|
||||||
Author : G. Barlas
|
|
||||||
Version : 1.0, September 2015
|
|
||||||
: 1.1, 16.12.2019 - Comments added (H. Weber)
|
|
||||||
: 1.2, 27.01.2022 - Console output improved (H. Weber, S. Stahl)
|
|
||||||
License : V 1.0 released under the GNU GPL 3.0
|
|
||||||
Description : Producer/consumer example using a monitor.
|
|
||||||
To compile : qmake monitor2ProdCons.pro; make
|
|
||||||
============================================================================
|
|
||||||
*/
|
|
||||||
#include "monitor.h"
|
#include "monitor.h"
|
||||||
#include "producer.h"
|
#include "producer.h"
|
||||||
#include "consumer.h"
|
#include "consumer.h"
|
Loading…
Reference in New Issue
Block a user