Thread programming a. Please cut, paste and finish the following program compose
ID: 3727582 • Letter: T
Question
Thread programming
a. Please cut, paste and finish the following program composed of 4 separate files below.
b. main() should:
Create 2 child threads, both that run evaluate(). The evaluate() function should be passed the address of nodeBuffer.
Run makeNode() NUM_PROBLEMS times, and put the returned node address in nodeBuffer.
Wait for both child threads to finish
c. evaluate() should NUM_PROBLEM/2 times do:
Save the value returned by the pullOut() method into a Node* variable.
Print the iteration number, the node expression (obtainable as a C-string with the expression: nodePtr->toString().c_str()) and the value the node evaluates to (nodePtr->eval()).
delete the node pointer variable
After the loop, the function should just return(NULL).
Stop and try your program now. It is multi-threaded, but not thread-safe. It should not work properly.
d. Make NodeBuffer thread safe by giving it the necessary mutex(es) and condition(s). Where is/are the critical sections? Be sure to destroy your variables in ~NodeBuffer()!
#include
Sample output:
Explanation / Answer
*** mathSolverHeader.h ***
// PURPOSE: To tell the maximum value that a tree can have.
const int MAX_VALUE = 64;
// PURPOSE: To tell how many problems to do.
const int NUM_PROBLEMS = 4096;
#include "Node.h"
#include "NodeBuffer.h"
*** Node.h ***
#include <string>
#include <sstream>
#include <unistd.h>
// PURPOSE: To distinguish among the mathematical operators.
typedef enum {
ADD_OP,
SUBTRACT_OP,
MULTIPLY_OP,
DIVIDE_OP,
NUM_OPS
}
operator_ty;
// PURPOSE: To serve as the base class for the Node classes.
class Node
{
public :
Node ()
{ }
virtual
~Node ()
{ }
virtual
double eval()
const
= 0;
virtual
std::string toString()
const
= 0;
};
// PURPOSE: To represent a constant.
class ConstNode : public Node
{
double constant_;
public :
ConstNode () :
Node(),
constant_((double)((rand() % MAX_VALUE) + 1) )
{ }
double eval ()
const
{ return(constant_); }
std::string toString ()
const
{
std::ostringstream stream;
stream << constant_;
return(stream.str());
}
};
// PURPOSE: To return a randomly generated Node.
extern
Node* makeNode ();
// PURPOSE: To represent an operation.
class OperatorNode : public Node
{
operator_ty operator_;
Node* lhsPtr_;
Node* rhsPtr_;
public :
OperatorNode () :
Node(),
operator_((operator_ty)(rand() % NUM_OPS)),
lhsPtr_(makeNode()),
rhsPtr_(makeNode())
{ }
~OperatorNode ()
{
delete(rhsPtr_);
delete(lhsPtr_);
}
double eval ()
const
{
double lhs = lhsPtr_->eval();
double rhs = rhsPtr_->eval();
double result;
switch (operator_)
{
case ADD_OP :
result = lhs + rhs;
break;
case SUBTRACT_OP :
result = lhs - rhs;
break;
case MULTIPLY_OP :
result = lhs * rhs;
break;
case DIVIDE_OP :
result = lhs / rhs;
break;
}
return(result);
}
std::string toString ()
const
{
std::ostringstream stream;
const char* operatorNameCPtr;
switch (operator_)
{
case ADD_OP :
operatorNameCPtr = " + ";
break;
case SUBTRACT_OP :
operatorNameCPtr = " - ";
break;
case MULTIPLY_OP :
operatorNameCPtr = " * ";
break;
case DIVIDE_OP :
operatorNameCPtr = " / ";
break;
}
stream << "(" << lhsPtr_->toString()
<< operatorNameCPtr
<< rhsPtr_->toString() << ")";
return(stream.str());
}
};
*** NodeBuffer.h ***
class NodeBuffer
{
enum { SIZE = 16 };
Node* array_[SIZE];
int inIndex_;
int outIndex_;
int numItems_;
public :
NodeBuffer ()
{
for (int i = 0; i < SIZE; i++)
{
array_[i] = NULL;
}
inIndex_ = outIndex_ = numItems_ = 0;
}
~NodeBuffer ()
{
}
int getNumItems () const
{ return(numItems_); }
void putIn (Node* nodePtr)
{
while (getNumItems() >= SIZE)
{
}
array_[inIndex_] = nodePtr;
inIndex_++;
numItems_++;
if (inIndex_ >= SIZE)
inIndex_ = 0;
}
Node* pullOut ()
{
while (getNumItems() <= 0)
{
}
Node* toReturn = array_[outIndex_];
array_[outIndex_] = NULL;
outIndex_++;
numItems_--;
if (outIndex_ >= SIZE)
outIndex_ = 0;
return(toReturn);
}
};
*** mathSolver.cpp ***
//
// Compile with:
// $ g++ mathSolver.cpp -o mathSolver -lpthread -g
//
#include "mathSolverHeader.h"
#include<iostream>
using namespace std;
void* evaluate(void* vPtr)
{
NodeBuffer* nodeBufferPtr = (NodeBuffer*)vPtr;
// YOUR CODE HERE
for(int i=0; i<NUM_PROBLEMS/2; i++) {
Node* nodePtr = nodeBufferPtr->pullOut ();
cout << endl << i << " " << nodePtr->toString().c_str() << " = " << nodePtr->eval();
nodePtr->~Node();
}
pthread_exit(NULL);
}
// PURPOSE: To return a randomly generated Node.
Node* makeNode ()
{
return( (rand() % 3) ? (Node*)new ConstNode() : (Node*)new OperatorNode() );
}
int main(int argc, char* argv[])
{
NodeBuffer nodeBuffer;
pthread_t consumer0;
pthread_t consumer1;
int toReturn = EXIT_SUCCESS;
srand( (argc < 2) ? getpid() : atoi(argv[1]) );
// YOUR CODE HERE
Node* node_p;
if(pthread_create(&consumer0, NULL, (void* (*)(void*))(makeNode), NULL)) {
fprintf(stderr, "Error creating thread ");
return 1;
}
void* temp = NULL;
pthread_join(consumer0, &temp);
node_p = (Node *)temp;
nodeBuffer.putIn(node_p);
if(pthread_create(&consumer1, NULL, evaluate, &nodeBuffer)) {
fprintf(stderr, "Error creating thread ");
return 1;
}
return(toReturn);
}
Related Questions
drjack9650@gmail.com
Navigate
Integrity-first tutoring: explanations and feedback only — we do not complete graded work. Learn more.