Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <iostream>
- #include <stdio.h>
- #include <stdlib.h>
- #include <errno.h>
- #include <string.h>
- #include <pthread.h>
- #include <semaphore.h>
- using namespace std;
- //sem_t semCout; // zorgt voor mutual excusive gebruik van cout (1 thread tegelijk).
- int foodCounter=0; // teller voor het aantal gevulde plaatsen van de buffer
- pthread_mutex_t mbuffer = PTHREAD_MUTEX_INITIALIZER; //mutex object om tegelijk de buffer bewerken te voorkomen
- pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER; //mutex object voor conditionele variabelen
- pthread_mutex_t mcout = PTHREAD_MUTEX_INITIALIZER; //mutex object om tegelijk de output bewerken te voorkomen
- pthread_cond_t isErEten = PTHREAD_COND_INITIALIZER;//als er eten is
- pthread_cond_t isHijVol = PTHREAD_COND_INITIALIZER;//als hij vol is
- void check_errno(int error) {
- if (error<0) {
- perror("Error");
- exit(EXIT_FAILURE);
- }
- }
- void check(int error) {
- if (error!=0) {
- cerr<<"Error: "<<strerror(error)<<endl;
- exit(EXIT_FAILURE);
- }
- }
- template<typename T, int size> // size moet een macht van 2 zijn (blijkt verderop)!
- class CircularBuffer {
- public:
- CircularBuffer(); // constructor zorgt voor de initialisatiie van de datamembers
- ~CircularBuffer();
- void put(const T& t); // schrijf element in de buffer. WACHT als buffer vol is!
- const T get(); // lees een element uit de buffer. WACHT als buffer leeg is!
- private:
- T buffer[size]; // buffer voor het opslaan van size elementen van het type T
- int indexGet; // index waar het volgende element uit de buffer gelezen wordt
- int indexPut; // index waar het volgende element in de buffer geschreven wordt
- //sem_t semMutualExclusive; // binaire semaphore: zorgt voor wederzijdse uitsluiting
- //sem_t semEmpty; // counting semaphore: telt aantal lege plaatsen
- //sem_t semFilled; // counting semaphore: telt aantal gevulde plaatsen
- };
- template<typename T, int size>
- CircularBuffer<T, size>::CircularBuffer(): indexGet(0), indexPut(0) {
- //check_errno( sem_init(&semMutualExclusive, 0, 1) ); // 1 thread tegelijk toelaten in critische gebied
- //check_errno( sem_init(&semEmpty, 0, size) ); // er zijn size lege plaatsen
- //check_errno( sem_init(&semFilled, 0, 0) ); // er zijn 0 gevulde plaatsen
- }
- template<typename T, int size>
- CircularBuffer<T, size>::~CircularBuffer() {
- //check_errno( sem_destroy(&semMutualExclusive) );
- //check_errno( sem_destroy(&semEmpty) );
- //check_errno( sem_destroy(&semFilled) );
- }
- template<typename T, int size>
- void CircularBuffer<T, size>::put(const T& t) {
- //check_errno( sem_wait(&semEmpty) ); // verlaag het aantal lege plaatsen. WACHT als er geen lege plaatsen zijn!
- pthread_mutex_lock(&m);
- while(foodCounter>=size)
- pthread_cond_wait(&isHijVol,&m);
- foodCounter++;
- //check_errno( sem_wait(&semMutualExclusive) ); // ga critisch gebied binnen
- check_errno(pthread_mutex_lock(&mbuffer));
- buffer[indexPut++]=t;
- indexPut&=size-1; // slim maar werkt alleen als size een macht van 2 is
- //check_errno( sem_post(&semMutualExclusive) ); // verlaat critische gebied
- check_errno(pthread_mutex_unlock(&mbuffer));
- pthread_cond_signal(&isErEten);
- //check_errno( sem_post(&semFilled) ); // verhoog het aantal gevulde plaatsen.
- pthread_mutex_unlock(&m);
- }
- template<typename T, int size>
- const T CircularBuffer<T, size>::get() {
- //check_errno( sem_wait(&semFilled) ); // verlaag het aantal gevulde plaatsen. WACHT als er geen gevulde plaatsen zijn!
- pthread_mutex_lock(&m);
- while(foodCounter<=0)
- pthread_cond_wait(&isErEten,&m);
- foodCounter--;
- //check_errno( sem_wait(&semMutualExclusive) ); // ga critische gebied binnen
- check_errno(pthread_mutex_lock(&mbuffer));
- T c(buffer[indexGet++]);
- indexGet&=size-1; // slim maar werkt alleen als size een macht van 2 is
- //check_errno( sem_post(&semMutualExclusive) ); // verlaat critische gebied
- check_errno(pthread_mutex_unlock(&mbuffer));
- pthread_cond_signal(&isHijVol);
- //check_errno( sem_post(&semEmpty) ); // verhoog het aantal lege plaatsen
- pthread_mutex_unlock(&m);
- return c;
- }
- CircularBuffer<char, 4> b;
- void* producer(void* arg) { // functie voor producer thread
- char c(*static_cast<char*>(arg));
- pthread_mutex_lock(&mcout); //check_errno( sem_wait(&semCout) );
- cout<<"Thread: "<<pthread_self()<<" met arg: "<<c<< " gestart"<<endl;
- pthread_mutex_unlock(&mcout); //check_errno( sem_post(&semCout) );
- for (int i(0); i<1000; ++i) {
- b.put(c);
- }
- pthread_mutex_lock(&mcout); //check_errno( sem_wait(&semCout) );
- cout<<"Thread: "<<pthread_self()<<" gestopt"<<endl;
- pthread_mutex_unlock(&mcout); //check_errno( sem_post(&semCout) );
- }
- void* consumer(void*) { // functie voor consumer thread
- pthread_mutex_lock(&mcout); //check_errno( sem_wait(&semCout) );
- cout<<"Thread: "<<pthread_self()<<" gestart"<<endl;
- pthread_mutex_unlock(&mcout); //check_errno( sem_post(&semCout) );
- for (int i(0); i<2000; ++i) {
- char c(b.get());
- pthread_mutex_lock(&mcout); //check_errno( sem_wait(&semCout) );
- cout<<c;
- pthread_mutex_unlock(&mcout); //check_errno( sem_post(&semCout) );
- }
- pthread_mutex_lock(&mcout); //check_errno( sem_wait(&semCout) );
- cout<<"Thread: "<<pthread_self()<<" gestopt"<<endl;
- pthread_mutex_unlock(&mcout); //check_errno( sem_post(&semCout) );
- }
- int main(int argc, char *argv[]) {
- // De main thread moet de hoogste prioriteit hebben omdat deze thread de andere threads start en
- // we willen de onderlinge wisselwerking van deze threads bestuderen!
- sched_param sp;
- int p;
- check( pthread_getschedparam(pthread_self(), &p, &sp) );
- sp.sched_priority=60;
- check( pthread_setschedparam(pthread_self(), SCHED_FIFO, &sp) );
- if (argc!=4) {
- cerr<<"Usage: opdr1.out <Priority Consumer> <Priority Frikadel Producer> <Priority Kroket Producer>"<<endl;
- exit (-1);
- }
- int prioc(atoi(argv[1]));
- int priop1(atoi(argv[2]));
- int priop2(atoi(argv[3]));
- cout<<"Output voor Consumer priority = "<<prioc
- <<" Frikadel Producer priority = "<<priop1
- <<" Kroket Producer priority = "<<priop2
- <<endl;
- //check_errno( sem_init(&semCout, 0, 1) );
- pthread_attr_t ptac, ptap1, ptap2;
- check( pthread_attr_init(&ptac) );
- check( pthread_attr_init(&ptap1) );
- check( pthread_attr_init(&ptap2) );
- check( pthread_attr_setinheritsched(&ptac, PTHREAD_EXPLICIT_SCHED) );
- check( pthread_attr_setinheritsched(&ptap1, PTHREAD_EXPLICIT_SCHED) );
- check( pthread_attr_setinheritsched(&ptap2, PTHREAD_EXPLICIT_SCHED) );
- check( pthread_attr_setschedpolicy(&ptac, SCHED_FIFO) );
- check( pthread_attr_setschedpolicy(&ptap1, SCHED_FIFO) );
- check( pthread_attr_setschedpolicy(&ptap2, SCHED_FIFO) );
- sched_param spc, spp1, spp2;
- check( pthread_attr_getschedparam(&ptac, &spc) );
- check( pthread_attr_getschedparam(&ptap1, &spp1) );
- check( pthread_attr_getschedparam(&ptap2, &spp2) );
- spc.sched_priority=prioc;
- spp1.sched_priority=priop1;
- spp2.sched_priority=priop2;
- check( pthread_attr_setschedparam(&ptac, &spc) );
- check( pthread_attr_setschedparam(&ptap1, &spp1) );
- check( pthread_attr_setschedparam(&ptap2, &spp2) );
- pthread_t ptp1, ptp2, ptc;
- char frikadel('F');
- char kroket('K');
- check( pthread_create(&ptc, &ptac, consumer, 0) );
- check( pthread_create(&ptp1, &ptap1, producer, static_cast<void*>(&frikadel)) );
- check( pthread_create(&ptp2, &ptap2, producer, static_cast<void*>(&kroket)) );
- check( pthread_join(ptc, 0) );
- check( pthread_join(ptp1, 0) );
- check( pthread_join(ptp2, 0) );
- //check_errno( sem_destroy(&semCout) );
- return EXIT_SUCCESS;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement