Academic Integrity: tutoring, explanations, and feedback — we don’t complete graded work or submit on a student’s behalf.

In C++ this task will implement the functions in the msgpass.cpp file. Given fil

ID: 3744335 • Letter: I

Question

In C++ this task will implement the functions in the msgpass.cpp file.

Given files:

//server.h

#ifndef SERVER_H

#define SERVER_H

#include <iostream>

#include <vector>

#include <fstream>

#include <mutex>

using namespace std;

class Server

{

public:

Server();

Server(string, int);

~Server();

string getPiece(int);

private:

string *ascii;

mutex access;

};

#endif

//server.cpp

#include "Server.h"

#include <unistd.h>

#include <time.h>

Server::Server(){}

Server::Server(string filename, int threads)

{

vector<string> loaded;

ascii = new string[threads];

ifstream in;

string line;

in.open(filename);

if (!in.is_open())

{

cout << "Could not open file " << filename << endl;

exit(1);

}

while(!in.eof())

{

getline(in, line);

loaded.push_back(line);

}

in.close();

int step = loaded.size()/threads;

string piece = "";

for (int i = 0; i < threads; ++i)

{

for (int j = step*i; j < ((step*i) + step); ++j)

{

if (j + 1 < loaded.size())

piece += loaded.at(j) + " ";

else

piece += loaded.at(j);

}

ascii[i] = piece;

piece = "";

}

}

Server::~Server()

{

delete []ascii;

}

string Server::getPiece(int piece)

{

srand(time(NULL));

if (rand()/static_cast<float>(RAND_MAX) > 0.80)

throw "500 Internal Server Error";

cout << "Getting piece number " << piece << endl;

string toReturn = ascii[piece];

return toReturn;

}

FILE TO IMPLEMENT

//msgpass.cpp

#include <iostream>

#include <queue>

#include <mutex>

#include <unistd.h>

#include <thread>

#include "Server.h"

using namespace std;

struct Message

{

string payload;

unsigned int t_ind;

};

class MsgPass

{

public:

MsgPass(unsigned int upper_b)

{

up_bound = upper_b;

}

~MsgPass(){}

void send(struct Message m)

{

msgqueue.push(m);

}

struct Message recv()

{

struct Message msg = msgqueue.front();

msgqueue.pop();

return msg;

}

bool isFull()

{

bool toReturn = false;

if (msgqueue.size() == up_bound)

toReturn = true;

return toReturn;

}

unsigned int getSize()

{

return msgqueue.size();

}

bool empty()

{

return msgqueue.empty();

}

private:

queue<Message> msgqueue;

unsigned int up_bound;

};

Server *server;

MsgPass *m;

void print(string toPrint)

{

}

void output(string out)

{

}

void lock(int choice)

{

}

void unlock(int choice)

{

}

void getAndWrite()

{

/* Receive all the messages from the message queue and print them in reverse order according to t_ind */

}

void passAlong(int index)

{

try

{

if (m->isFull())

{

getAndWrite();

}

else

{

lock(0); // server

print("Thread " + to_string(index) + ": Lock acquired for Server ");

string piece = server->getPiece(index);

unlock(0);

print("Thread " + to_string(index) + ": Lock released for Server ");

/* Construct the message using the Message struct. Call it msg */

m->send(msg);

lock(1);

output("Thread " + to_string(index) + " sending message ");

unlock(1);

}

}

catch (const char* err)

{

cout << err << endl;

throw new exception();

}

}

int main(int argc, char const *argv[])

{

/* cin here */

if (/*input 2*/ != 0 && /*input 1*/ != 0)

{

server = new Server(/*input 2*/, /*input 1*/);

m = new MsgPass(/*input 1*/);

/* Fill in the main function code here */

delete server;

delete m;

}

else

{

cout << "Please enter a file name and the number of threads to use!" << endl;

}

return 0;

}

batman.ascii

*******************
***************************
*********************************
******* * * * * *******
******* *** ** ** *** *******
****** ***** ********* ***** *****
****** ******** ********* ****** *****
**** ********** ********* ********* *****
**** ************** *********** ************ ****
**** ************************************************* ****
**** *************************************************** ****
**** **************************************************** ****
**** **************************************************** ****
**** *************************************************** ****
**** ******* **** *********** **** ********* ****
**** ***** * ******* * ******** ****
***** **** ***** ****** *****
***** ** *** ** ******
****** * * * *******
******* *******
******** *******
*********************************
***************************
*******************

This task still has the same scenario where each client can send their piece to the printe between the clients/threads. The idea is that after cach client/thread has requested the piece from the server, that piece, along with the client/thread index, will be sent (in this case by pushing them onto the message queue) to a single client/thread who is acting as a mediator for the print job. Once all pieces have been pushed onto the queue, the mediator client/thread will receive (in this case by popping the pieces off the message queue individually) all the messages and send them to the printer in reverse order r, however this time you decide to use a message queue to emulate message passing

Explanation / Answer

//server.h

#ifndef SERVER_H

#define SERVER_H

#include <iostream>

#include <vector>

#include <fstream>

#include <mutex>

using namespace std;

class Server

{

public:

Server();

Server(string, int);

~Server();

string getPiece(int);

private:

string *ascii;

mutex access;

};

#endif

//server.cpp

#include "Server.h"

#include <unistd.h>

#include <time.h>

Server::Server(){}

Server::Server(string filename, int threads)

{

vector<string> loaded;

ascii = new string[threads];

ifstream in;

string line;

in.open(filename);

if (!in.is_open())

{

cout << "Could not open file " << filename << endl;

exit(1);

}

while(!in.eof())

{

getline(in, line);

loaded.push_back(line);

}

in.close();

int step = loaded.size()/threads;

string piece = "";

for (int i = 0; i < threads; ++i)

{

for (int j = step*i; j < ((step*i) + step); ++j)

{

if (j + 1 < loaded.size())

piece += loaded.at(j) + " ";

else

piece += loaded.at(j);

}

ascii[i] = piece;

piece = "";

}

}

Server::~Server()

{

delete []ascii;

}

string Server::getPiece(int piece)

{

srand(time(NULL));

if (rand()/static_cast<float>(RAND_MAX) > 0.80)

throw "500 Internal Server Error";

cout << "Getting piece number " << piece << endl;

string toReturn = ascii[piece];

return toReturn;

}

//msgpass.cpp

#include <iostream>

#include <queue>

#include <mutex>

#include <unistd.h>

#include <thread>

#include "Server.h"

using namespace std;

struct Message

{

string payload;

unsigned int t_ind;

};

class MsgPass

{

public:

MsgPass(unsigned int upper_b)

{

up_bound = upper_b;

}

~MsgPass(){}

void send(struct Message m)

{

msgqueue.push(m);

}

struct Message recv()

{

struct Message msg = msgqueue.front();

msgqueue.pop();

return msg;

}

bool isFull()

{

bool toReturn = false;

if (msgqueue.size() == up_bound)

toReturn = true;

return toReturn;

}

unsigned int getSize()

{

return msgqueue.size();

}

bool empty()

{

return msgqueue.empty();

}

private:

queue<Message> msgqueue;

unsigned int up_bound;

};

Server *server;

MsgPass *m;

void print(string toPrint)

{

}

void output(string out)

{

}

void lock(int choice)

{

}

void unlock(int choice)

{

}

void getAndWrite()

{

/* Receive all the messages from the message queue and print them in reverse order according to t_ind */

}

void passAlong(int index)

{

try

{

if (m->isFull())

{

getAndWrite();

}

else

{

lock(0); // server

print("Thread " + to_string(index) + ": Lock acquired for Server ");

string piece = server->getPiece(index);

unlock(0);

print("Thread " + to_string(index) + ": Lock released for Server ");

/* Construct the message using the Message struct. Call it msg */

m->send(msg);

lock(1);

output("Thread " + to_string(index) + " sending message ");

unlock(1);

}

}

catch (const char* err)

{

cout << err << endl;

throw new exception();

}

}

int main(int argc, char const *argv[])

{

/* cin here */

if (/*input 2*/ != 0 && /*input 1*/ != 0)

{

server = new Server(/*input 2*/, /*input 1*/);

m = new MsgPass(/*input 1*/);

/* Fill in the main function code here */

delete server;

delete m;

}

else

{

cout << "Please enter a file name and the number of threads to use!" << endl;

}

return 0;

}