Part 1: Producer-Consumer - execution (0 points) The producer_consumer.cpp progr
ID: 3755888 • Letter: P
Question
Part 1: Producer-Consumer - execution (0 points)
The producer_consumer.cpp program given to you simulates a highly simplified restaurant order taking and processing system using pthreads. Study this program, using the comments in the code to help you understand the functionality.
Build and execute this program multiple times. You will observe that the program behaves strangely:
Some random, dummy orders that were never placed may get processed.
Some orders entered by the user may not be processed at all.
The message “Phew! Done with orders for today!” may get printed even before orders are placed.
All these problems arise because of lack of synchronization among the processOrders and takeOrders threads.
#include <pthread.h>
#include <iostream>
#include <unistd.h>
#include <cstdlib>
#include <mutex>
using namespace std;
#define MAX 10
#define N 4
// Data structure to represent a simplified Order
// that has an order number and an item number.
struct Order
{
int order_num;
int item_num;
};
Order new_orders [N]; // array of elements of type Order to be used as a shared buffer
int num_new_orders = 0; // count of number of new (i.e., unprocessed) orders
int order_num = 0; // global variable used to generate unique order numbers
// TODO: Define and initialize necessary mutex and condition variables here
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t not_empty = PTHREAD_COND_INITIALIZER;
pthread_cond_t not_full = PTHREAD_COND_INITIALIZER;
int buffer[N];
int count = 0;
void* takeOrders(void* arg)
{
int item;
int index = 0;
for(int i = 0; i < MAX; ++i) {
// Beginning of critical region 1
// Get user input
cout << "Enter a menu item number between 1 and 50: ";
cin >> item;
// Print new order's details
cout << "Got new order! Order number is " << order_num << " and item number: " << item << std::endl;
// End of critical region 1
// Beginning of critical region 2
// Put new order into new orders buffer and update number of new orders
new_orders[index].order_num = order_num;
new_orders[index++].item_num = item;
++num_new_orders;
// End of critical region 2
// Update order number so that next order gets a different number
++order_num;
// If the end of the new orders buffer is reached, wrap back around
if(index == N)
index = 0;
}
pthread_exit(NULL);
}
void* processOrders(void* arg)
{
int item;
int index = 0;
int o_num;
for(int i = 0; i < MAX; ++i) {
// Beginning of critical region 3
// Retrieve new order details from buffer and update number of new orders
o_num = new_orders[index].order_num;
item = new_orders[index++].item_num;
--num_new_orders;
// End of critical region 3
// Beginning of critical region 4
// Print retrieved order's details
cout << "Processing order number " << o_num << " with item number: " << item << std::endl;
// End of critical region 4
// Suspend self for 1 second
sleep(1);
// If the end of the new orders buffer is reached, wrap back around
if(index == N)
index = 0;
}
pthread_exit(NULL);
}
int main()
{
// Create threads to take and process orders
pthread_t id1, id2;
pthread_create(&id1, NULL, processOrders, NULL);
pthread_create(&id2, NULL, takeOrders, NULL);
// TODO: Add code to wait for both threads to finish
void* consumer(void* arg) {
int item; int curr_pos = 0;
for(int i = 0; i < 100; ++i){
pthread_mutex_lock(&mutex);
if(count == 0)
pthread_cond_wait(¬_empty, &mutex);
cout << "Consuming ” << buffer[curr_pos++] << endl;
if(curr_pos == N) curr_pos = 0; ––count;
pthread_cond_signal(¬_full);
pthread_mutex_unlock(&mutex);
}
}
void* producer(void* arg)
{
int item; int curr_pos = 0;
for(int i = 0; i < 100; ++i) {
pthread_mutex_lock(&mutex);
pthread_cond_wait(¬_full, &mutex);
buffer[curr_pos++] = rand();
cout << "Producing " <<
buffer[curr_pos-1] << endl;
if(curr_pos == N) curr_pos = 0;
++count;
pthread_cond_signal(¬_empty);
pthread_mutex_unlock(&mutex);
}
// Print goodbye message
cout << "Phew! Done with orders for today!" << endl;
pthread_exit(NULL);
}
This is my code I was supposed to add on to the commented sections that say tofo but i keep runnig into error. Id greatfuly appericate any help with detailed explenations of my errors or missing code.
Explanation / Answer
#include <pthread.h>
#include <iostream>
#include <unistd.h>
#include <cstdlib>
#include <mutex>
using namespace std;
#define MAX 10
#define N 4
// Data structure to represent a simplified Order
// that has an order number and an item number.
struct Order
{
int order_num;
int item_num;
};
Order new_orders [N]; // array of elements of type Order to be used as a shared buffer
int num_new_orders = 0; // count of number of new (i.e., unprocessed) orders
int order_num = 0; // global variable used to generate unique order numbers
// TODO: Define and initialize necessary mutex and condition variables here
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t not_empty = PTHREAD_COND_INITIALIZER;
pthread_cond_t not_full = PTHREAD_COND_INITIALIZER;
int buffer[N];
int count = 0;
void* takeOrders(void* arg)
{
int item;
int index = 0;
for(int i = 0; i < MAX; ++i) {
// Beginning of critical region 1
// Get user input
cout << "Enter a menu item number between 1 and 50: ";
cin >> item;
// Print new order's details
cout << "Got new order! Order number is " << order_num << " and item number: " << item << std::endl;
// End of critical region 1
// Beginning of critical region 2
// Put new order into new orders buffer and update number of new orders
new_orders[index].order_num = order_num;
new_orders[index++].item_num = item;
++num_new_orders;
// End of critical region 2
// Update order number so that next order gets a different number
++order_num;
// If the end of the new orders buffer is reached, wrap back around
if(index == N)
index = 0;
}
pthread_exit(NULL);
}
void* processOrders(void* arg)
{
int item;
int index = 0;
int o_num;
for(int i = 0; i < MAX; ++i) {
// Beginning of critical region 3
// Retrieve new order details from buffer and update number of new orders
o_num = new_orders[index].order_num;
item = new_orders[index++].item_num;
--num_new_orders;
// End of critical region 3
// Beginning of critical region 4
// Print retrieved order's details
cout << "Processing order number " << o_num << " with item number: " << item << std::endl;
// End of critical region 4
// Suspend self for 1 second
sleep(1);
// If the end of the new orders buffer is reached, wrap back around
if(index == N)
index = 0;
}
pthread_exit(NULL);
}
int main()
{
// Create threads to take and process orders
pthread_t id1, id2;
pthread_create(&id1, NULL, processOrders, NULL);
pthread_create(&id2, NULL, takeOrders, NULL);
// TODO: Add code to wait for both threads to finish
void* consumer(void* arg) {
int item; int curr_pos = 0;
for(int i = 0; i < 100; ++i){
pthread_mutex_lock(&mutex);
if(count == 0)
pthread_cond_wait(¬_empty, &mutex);
cout << "Consuming ” << buffer[curr_pos++] << endl;
if(curr_pos == N) curr_pos = 0; ––count;
pthread_cond_signal(¬_full);
pthread_mutex_unlock(&mutex);
}
}
void* producer(void* arg)
{
int item; int curr_pos = 0;
for(int i = 0; i < 100; ++i) {
pthread_mutex_lock(&mutex);
pthread_cond_wait(¬_full, &mutex);
buffer[curr_pos++] = rand();
cout << "Producing " <<
buffer[curr_pos-1] << endl;
if(curr_pos == N) curr_pos = 0;
++count;
pthread_cond_signal(¬_empty);
pthread_mutex_unlock(&mutex);
}
// Print goodbye message
cout << "Phew! Done with orders for today!" << endl;
pthread_exit(NULL);
}