dimanche 26 novembre 2017

Why am I getting different outputs? I am coding with c++ using a bounded buffer, pthreads, and semaphores

I believe my logic is correct from my understanding of semaphores. It is the producer/consumer problem. Producer generates a random letter, decrements empty buffer by 1, decrements mutex to get permission to enter its critical section, then within the critical section it adds the random letter to the buffer, thereafter increments mutex, then increments full. Consumer waits until full is greater than 0, decrements mutex to see if it can enter its critical section, within the critical section the random letter will be taken from the buffer and will do some calculations, then it will increment mutex and increment empty.

The problem I'm having is that I keep getting different outputs when I run the program. There seems to be no order in which I get them. Some of the outputs are correct and some are wrong. Why am I getting different outputs? Here is my code and outputs:

#include <iostream>
#include <pthread.h>
#include <string>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <semaphore.h>
#include <cstring>
using namespace std;

void* consumer(void*);
void* producer(void*);

string buffer[3];
int put = 0;
int get = 0;
sem_t mutex;
sem_t empty;
sem_t full;
int pw = 0;
int cw = 0;
string alpha = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";

int main() {

    sem_init(&mutex, 0, 1);
    sem_init(&empty, 0, 3);
    sem_init(&full, 0, 0);

    pthread_t consumerThread;
    pthread_t producerThread;
    pthread_create(&producerThread, NULL, &producer, NULL);
    pthread_create(&consumerThread, NULL, &consumer, NULL);
    pthread_join(producerThread, NULL);
    pthread_join(consumerThread, NULL);

    sem_destroy(&mutex);
    sem_destroy(&empty);
    sem_destroy(&full);  

    return 0;
  }

void* producer(void*) {

  while (pw < 6) {
    pw++;

    //srand(time(NULL));
    int a1 = rand() % 25;
    cout << "producer: " << alpha[a1] << endl;

    sem_wait(&empty);
    sem_wait(&mutex);

    buffer[put] = alpha[a1];
    put = (put + 1) % 3;

    sem_post(&mutex);
    sem_post(&full);

    }
    return 0;
    }

void* consumer(void*) {

  while (cw < 6) {
    cw++;

    sem_wait(&full);
    sem_wait(&mutex);       

    string c = (1, buffer[get]);
    buffer[get] = "";
    get = (get + 1) % 3;

    int a;
    int v1;
    int v2;
    int d1;
    int d2;
    string S;
    string T;
    for (int i = 0; i < alpha.length(); i++) {
        if (alpha[i] == c[0]) {
            a = i;
        }
    }

    if (a % 2 == 0) {

        if (a == 0) {
            v1 = 20;
            v2 = 4;
        } else if (a > 0 && a < 4) {
            v1 = 0;
            v2 = 4;
        } else if (a == 4) {
            v1 = 0;
            v2 = 8;
        } else if (a > 4 && a < 8) {
            v1 = 4;
            v2 = 8;
        } else if (a == 8) {
            v1 = 4;
            v2 = 14;
        } else if (a > 8 && a < 14) {
            v1 = 8;
            v2 = 14;
        } else if (a == 14) {
            v1 = 8;
            v2 = 20;
        } else if (a > 14 && a < 20) {
            v1 = 14;
            v2 = 20;
        } else if (a == 20) {
            v1 = 14;
            v2 = 0;
        } else if (a > 20 && a <= 25) {
            v1 = 20;
            v2 = 0;
        } else {
            cout << "error with v1 and v2, incorrect index" << endl;
        }

        S = alpha[v1] + c + alpha[v2];

        if (v1 > a) {
            d1 = a - v1 + 26;
        } else {
            d1 = a - v1;
        }

        if (a > v2) {
            d2 = (25 - v2) % 25;
        } else {
            d2 = v2 - a;
        }

        if (d1 > d2) {
            T = alpha[v1] + S + alpha[v1];
        } else if (d2 > d1) {
            T = alpha[v2] + S + alpha[v2];
        } else {
            //cout << "Both distances are the same." << endl;
        }

        cout << alpha[a] << alpha[v1] << alpha[v2] << S << " - c to v1: " << d1 << " - c to v2: " << d2 << endl;           

        if (d1 > d2) {
            cout << "The distance from c to v1 is larger: " << d1 << endl;
        } else if (d2 > d1) {
            cout << "The distance from c to v2 is larger: " << d2 << endl;
        } else {
            cout << "The distances are the same: " << d1 << endl;
        }

        //testing
        //cout << "v1: " << v1 << endl;
        //cout << "v2: " << v2 << endl;
        //cout << "d1: " << d1 << endl;
        //cout << "d2: " << d2 << endl;

    } else {
        cout << "consumer: " << alpha[a] << endl;
    }
    sem_post(&mutex);
    sem_post(&empty);
}

return 0;
}

Outputs:

output 1:

producer: I
producer: L
producer: C
producer: P
IEOEIO - c to v1: 4 - c to v2: 6
The distance from c to v2 is larger: 6
consumer: L
CAEACE - c to v1: 2 - c to v2: 2
The distances are the same: 2
producer: S
consumer: P
producer: K
SOUOSU - c to v1: 4 - c to v2: 2
The distance from c to v1 is larger: 4
KIOIKO - c to v1: 2 - c to v2: 4
The distance from c to v2 is larger: 4

RUN FINISHED; exit value 0; real time: 0ms; user: 0ms; system: 0ms

output 2:

producer: I
producer: L
IEOEIO - c to v1: 4 - c to v2: 6
The distance from c to v2 is larger: 6
producer: C
consumer: L
producer: P
CAEACE - c to v1: 2 - c to v2: 2
The distances are the same: 2
producer: S
consumer: P
producer: K
SOUOSU - c to v1: 4 - c to v2: 2
The distance from c to v1 is larger: 4
KIOIKO - c to v1: 2 - c to v2: 4
The distance from c to v2 is larger: 4

RUN FINISHED; exit value 0; real time: 0ms; user: 0ms; system: 0ms

It seems like the buffer is working fine as everything put inside is coming out and not being deleted or ignored, by there should never be 4 producer outputs in a row as this would go over the buffer size(3). Also consumer does replace the value in value with empty, so I believe this may be a syncing error I'm having. Again thank you for the input.

Aucun commentaire:

Enregistrer un commentaire