Help with writing C++ code using mutexes OBJECTIVES This rather short assignment
ID: 3824883 • Letter: H
Question
Help with writing C++ code using mutexes
OBJECTIVES This rather short assignment should teach you how to use pthreads, pthread mutexes and pthread condition variables THE PROBLEM A bridge is load-zoned and can only carry a total wet ght of maxweight tons. Your solution should ensure that the total weight of all vehicles on the bridge will never exceed its maximum load. Each vehicle will be represented by a separate thread and all inter-thread synchronization must be implemented through pthread mutexes and pthread condition variables. You cannot use senna Vehicles whose total loaded we exceeds the oad of the bridge should be rejected and a descriptive message containing the serial number of the vehicle printed out. YOUR PROGRAM Your program should consist of l. A main program, 2. An enter Bridge (weight) method to be performed by each arriving vehicle 3. A leave Bridge(weight) method to be performed by each vehicle leaving the bridge, and 4. One child thread per vehicle. The maxweight constant should be read from the mmand line as in /a.out 10 All other parameters will be re ad from the standard input. Each input line will describe one vehicle arriving at the bridge and will contain four parameters An alphanumeric string without spaces representing the car license plate, 2. A positive integer representing the number of seconds elapsed since the arrival ofthe previous vehicle (it wi be equal to zero for the first vehicle arriving to the bridge) 3. A positive integer representing the total loaded weight of the vehicle rounded up to an integer number of tons, 4. A positive integer representing the number of seconds the vehicle will take to cross the bridge. A possible set ofinput could be: HIOFCR. 1 10 STOL3N 3 10 20 SHKSPR. 1 30 2DIE4 BYOFCR. 1 15 Your main program should read the input lineper line, wait for the appropriate amount of time and fork a differen child process for each incoming vehicle. It should print out a descriptive message including the vehicle license number and the current bridge load every time a vehicle: l. Arrives at the bridge, 2. Starts crossing the bridge, and 3. Leaves the bridge The current bridge load when a vehicle starts cros the bridge includes the wei right of that vehicle but the current bridge load after a vehicle leaves the bridge does not. HINTS Create your mutexes and your condition variables in your main program before you fork any child thread. This document was updated last on Thursday, April 06, 2017 PTHREADS I. Dont forget the pthread include: #includeExplanation / Answer
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/wait.h>
#include <semaphore.h>
#include <errno.h>
#include <assert.h>
#include <fcntl.h>
#include <time.h>
#include <iostream>
#include <vector>
#include <sstream>
using namespace std;
#define SHARED_MEMORY_MUTEX "JP_Shared_Memory_Mutex"
#define BRIDGE_OVERWEIGHT_LOCK_GUARD "JP_BridgeOverweightLockGuard"
#define SHM_SZ 2048
#define MAX_WAITING_VEHICLES 100
// Helper method to simulate time delay
void Delay(double delayInSeconds)
{
clock_t before = clock();
while (true)
{
clock_t now = clock();
double time = (now - before) / (double) CLOCKS_PER_SEC;
// Break out of loop, if approximately one ms has elapsed;
if (time >= delayInSeconds)
{
break;
}
}
}
struct BridgeStat
{
int waitingVehicles;
long currentWeight;
};
class ConcurrencyManager
{
int sharedMemorySegmentId;
public:
sem_t * sharedMemoryMutex;
void * sharedMemorySegment;
sem_t * overweightLockGuard;
ConcurrencyManager()
{
sharedMemorySegment = NULL;
sharedMemoryMutex = SEM_FAILED;
overweightLockGuard = SEM_FAILED;
sharedMemorySegmentId = -1;
}
int Initialize()
{
// Initalize shared memory mutex
sharedMemoryMutex = sem_open(SHARED_MEMORY_MUTEX, O_CREAT, 0600, 1);
if (sharedMemoryMutex == SEM_FAILED)
{
return -1;
}
// Initialize overweight lock guard
overweightLockGuard = sem_open(BRIDGE_OVERWEIGHT_LOCK_GUARD, O_CREAT, 0600, 0);
if (overweightLockGuard == SEM_FAILED)
{
return -1;
}
cout << "Initialized shared memory mutex" << endl;
// Initialize shared memory segment
key_t key = 987612345;
sharedMemorySegmentId = shmget(key, SHM_SZ, 0600 | IPC_CREAT);
cout << "Segment Id: " << sharedMemorySegmentId << endl;
if (sharedMemorySegmentId < 0)
{
return sharedMemorySegmentId;
}
cout << "Initialized shared memory segment" << endl << endl;
// Retrieve the shared segment
sharedMemorySegment = shmat(sharedMemorySegmentId, 0, 0);
if (sharedMemorySegment == NULL)
{
return -1;
}
memset(sharedMemorySegment, 0, sizeof(BridgeStat));
return 0;
}
~ConcurrencyManager()
{
if (sharedMemorySegmentId >= 0)
{
if (sharedMemorySegment != NULL)
{
shmdt(sharedMemorySegment);
}
sem_wait(sharedMemoryMutex);
shmctl(sharedMemorySegmentId, IPC_RMID, NULL);
sem_post(sharedMemoryMutex);
}
if (sharedMemoryMutex != SEM_FAILED)
{
sem_unlink(SHARED_MEMORY_MUTEX);
}
if (overweightLockGuard != SEM_FAILED)
{
sem_unlink(BRIDGE_OVERWEIGHT_LOCK_GUARD);
}
}
};
class ScopedLock
{
sem_t * semaphore;
public:
ScopedLock(sem_t * _semaphore)
{
semaphore = _semaphore;
sem_wait(semaphore);
}
~ScopedLock()
{
sem_post(semaphore);
}
};
long MaxWeight = 0;
void EnterBridge(const ConcurrencyManager& concurrencyManager, int weight, string vehicle_plate_no)
{
bool canEnterBridge = false;
{
ScopedLock sharedMemoryMutex(concurrencyManager.sharedMemoryMutex);
BridgeStat * bridgeStat = (BridgeStat *) (concurrencyManager.sharedMemorySegment);
canEnterBridge = weight + bridgeStat->currentWeight <= MaxWeight && bridgeStat->waitingVehicles == 0;
if (canEnterBridge)
{
bridgeStat->currentWeight = bridgeStat->currentWeight + weight;
cout << "Vehicle with Plate #" << vehicle_plate_no << " started crossing the bridge" << endl;
cout << "Bridge load: " << bridgeStat->currentWeight << endl << endl;
return;
}
}
while (!canEnterBridge)
{
{
ScopedLock sharedMemoryMutex(concurrencyManager.sharedMemoryMutex);
BridgeStat * bridgeStat = (BridgeStat *)(concurrencyManager.sharedMemorySegment);
bridgeStat->waitingVehicles = bridgeStat->waitingVehicles + 1;
}
sem_wait(concurrencyManager.overweightLockGuard);
{
ScopedLock sharedMemoryMutex(concurrencyManager.sharedMemoryMutex);
BridgeStat * bridgeStat = (BridgeStat *) (concurrencyManager.sharedMemorySegment);
canEnterBridge = weight + bridgeStat->currentWeight <= MaxWeight;
if (canEnterBridge)
{
bridgeStat->waitingVehicles = bridgeStat->waitingVehicles - 1;
bridgeStat->currentWeight = bridgeStat->currentWeight + weight;
cout << "Vehicle with Plate #" << vehicle_plate_no << " started crossing the bridge" << endl;
cout << "Bridge load: " << bridgeStat->currentWeight << endl << endl;
}
}
}
}
void LeaveBridge(const ConcurrencyManager& concurrencyManager, int weight, string vehicle_plate_no)
{
ScopedLock sharedMemoryMutex(concurrencyManager.sharedMemoryMutex);
BridgeStat * bridgeStat = (BridgeStat *)(concurrencyManager.sharedMemorySegment);
bridgeStat->currentWeight = bridgeStat->currentWeight - weight;
cout << "Vehicle with Plate #" << vehicle_plate_no << " is leaving the bridge" << endl;
cout << "Bridge load: " << bridgeStat->currentWeight << endl << endl;
// Signal if there are waiters
if (bridgeStat->waitingVehicles > 0)
{
sem_post(concurrencyManager.overweightLockGuard);
}
}
int main(int argc, char *argv [])
{
if (argc != 2)
{
fprintf(stderr, "Usage: %s <max_weight> ", argv[0]);
return 1;
}
MaxWeight = strtoul(argv[1], NULL, 0);
cout << "Max Weight: " << MaxWeight << endl << endl;
ConcurrencyManager concurrencyManager;
if (concurrencyManager.Initialize() < 0)
{
fprintf(stderr, "Synchronization objects initializaton failed: %s ", strerror(errno));
return 1;
}
string vehicle_plate_no;
int arrival, weight, bridge_travel_time;
cin >> vehicle_plate_no >> arrival >> weight >> bridge_travel_time;
while (cin)
{
if (weight > MaxWeight)
{
cout << "Vehicle with Plate #" << vehicle_plate_no << " is overweight and rejected from the bridge" << endl << endl;
cin >> vehicle_plate_no >> arrival >> weight >> bridge_travel_time;
}
else
{
// Apply delay between arrivals if necessary
Delay(arrival);
{
ScopedLock sharedMemoryMutex(concurrencyManager.sharedMemoryMutex);
BridgeStat * bridgeStat = (BridgeStat *)(concurrencyManager.sharedMemorySegment);
cout << "Vehicle with Plate #" << vehicle_plate_no << " arrives at the bridge" << endl;
cout << "Bridge load: " << bridgeStat->currentWeight << endl << endl;
}
// Fork a new process for each person arriving in the plaza
int pid = fork();
if (pid == 0)
{
EnterBridge(concurrencyManager, weight, vehicle_plate_no);
Delay(bridge_travel_time);
LeaveBridge(concurrencyManager, weight, vehicle_plate_no);
return 0;
}
else if (pid > 0)
{
cin >> vehicle_plate_no >> arrival >> weight >> bridge_travel_time;
}
else
{
fprintf(stderr, "Failed to fork new process: %s ", strerror(errno));
return 1;
}
}
}
while (waitpid(-1, NULL, 0))
{
// The calling process does not have any unwaited-for children
if (errno == ECHILD)
{
break;
}
}
return 0;
}
Related Questions
drjack9650@gmail.com
Navigate
Integrity-first tutoring: explanations and feedback only — we do not complete graded work. Learn more.