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

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);

}

Hire Me For All Your Tutoring Needs
Integrity-first tutoring: clear explanations, guidance, and feedback.
Drop an Email at
drjack9650@gmail.com
Chat Now And Get Quote