logo Use CA10RAM to get 10%* Discount.
Order Nowlogo
(5/5)

How well did your program work after making it thread safe?

INSTRUCTIONS TO CANDIDATES
ANSWER ALL QUESTIONS

#include <cstdlib>

#include <cstdio>

#include <unistd.h>

#include <pthread.h>

 

 

//-- Constants: --//

 

//  PURPOSE:  To the names of the children

const char*    CHILD_NAME_ARRAY[]

= {"Alice",

   "Bob",

   "Cathy",

   "David"

  };

 

//  PURPOSE:  To tell the number of children.

const int NUM_CHILDREN = sizeof(CHILD_NAME_ARRAY)/sizeof(const char*);

 

//  PURPOSE:  To tell the possible denominations of the Coin instances.

const int COIN_DENOMINATION_ARRAY[]

= {1,5,10,25};

 

//  PURPOSE:  To tell the number of coins in each new Purse.

const int NUM_COINS_PER_NEW_PURSE

= 4;

 

//  PURPOSE:  To tell the number of denominations.

const int      NUM_DENOMINATIONS

= sizeof(COIN_DENOMINATION_ARRAY)/sizeof(int);

 

//  PURPOSE:  To tell how much money needs to be collected to buy the candy.

const int CANDY_COST = 100;

 

//-- Classes: --//

 

//  PURPOSE:  To represent coins.

class Coin

{

  //  I.  Member vars:

  //  PURPOSE:  To tell the denomination of '*this' Coin instance.

  int denomination_;

 

  //  PURPOSE:  To hold the address of the next Coin after '*this' one,

  //  or 'NULL' if there is no such Coin instance.

  Coin* nextPtr_;

 

  //  II.  Disallowed auto-generated methods:

  //  No default constructor:

  Coin ();

 

  //  No copy constructor:

  Coin (const Coin&);

 

  //  No copy assignment op:

  Coin operator= (const Coin&);

 

protected :

  //  III.  Protected methods:

 

public :

  //  IV.  Constructor(s), assignment op(s), factory(s) and destructor:

  //  PURPOSE:  To make a coin of denomination 'newDom'.  No return value.

  Coin (int newDom

) :

denomination_(newDom),

nextPtr_(NULL)

{ }

 

  //  PURPOSE:  To release the resources of '*this'.  No parameters.

  //  No return value.

  ~Coin ()

{

}

 

  //  V.  Accessors:

  //  PURPOSE:  To return the denomination of '*this' Coin instance.

  // No parameters.

  int getDenomination ()

  const

{ return(denomination_); }

 

  //  PURPOSE:  To return the address of the next Coin after '*this' one,

  //  or 'NULL' if there is no such Coin instance.  No parameters.

  Coin* getNextPtr ()

const

{ return(nextPtr_); }

 

  //  VI.  Mutators:

  //  PURPOSE:  To note that the Coin instance with address 'coinPtr' comes

  //  after '*this' one.  No return value.

  void       setNextPtr      (Coin* coinPtr

)

{

  nextPtr_ = coinPtr;

}

 

  //  VII.  Methods that do main and misc work of class:

  //  PURPOSE:  To create and return the address of a random coin.

  // No parameters.

  static

  Coin* makeRandom ()

  {

    //  I.  Application validity check:

 

    //  II.  Create and return a coin:

    return(new Coin(COIN_DENOMINATION_ARRAY[rand() % NUM_DENOMINATIONS]));

  }

 

};

 

 

 

 

//  PURPOSE:  To implement a list of Coin instances.

class Purse

{

  //  0.  Constants:

  enum

  {

    NO_OWNER_INDEX = -1

  };

 

  //  I.  Member var:

  //  PURPOSE:  To hold the index of the name of the owner of '*this' Purse

  // instance, or 'NO_OWNER_INDEX' if '*this' has no owner.

  int index_;

 

  //  ADD YOUR VARIABLES HERE

 

  //  II.  Disallowed auto-generated methods:

  //  No copy constructor:

  Purse (const Purse&);

 

  //  No copy-assignment op:

  Purse operator= (const Purse&);

 

protected :

  //  III.  Protected methods:

 

public :

  //  IV.  Constructor(s), assignment op(s), factory(s) and destructor:

  //  PURPOSE:  To initialize '*this' to an empty purse

  Purse () :

index_(NO_OWNER_INDEX)

  {

    //  INITIALIZE YOUR VARS HERE

  }

 

 

  //  PURPOSE:  To initialize '*this' Purse instance to have

  // NUM_COINS_PER_NEW_PURSE random Coin instances owned by the child with

  // index 'newIndex'.  No return value.

  Purse (int newIndex

  ) :

index_(newIndex)

  {

    //  INITIALIZE YOUR VARS HERE

 

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

    {

      addToBack(Coin::makeRandom());

    }

  }

 

 

  //  PURPOSE:  To release the resources of '*this'.  No parameters.

  //  No return value.

  ~Purse ()

  {

    Coin* run;

    Coin* nextPtr;

 

    //  GET RID OF YOUR VARS HERE

 

  }

 

 

  //  V.  Accessors:

  //  PURPOSE:  To return the index of the name of the owner of '*this' Purse

  // instance, or 'NO_OWNER_INDEX' if '*this' has no owner.

  int getIndex ()

const

{ return(index_); }

 

  //  PURPOSE:  To return the name of the owner of '*this' Purse instance.

  // No parameters.

  const char* getOwnerNameCPtr()

const

{

  return( (getIndex() == NO_OWNER_INDEX)

    ? "common"

  : CHILD_NAME_ARRAY[getIndex()]

);

}

 

  //  PURPOSE:  To return the value of the money in '*this' wallet.

  // No parameters.

  int getValue ()

const

  {

    const Coin* run;

    int sum = 0;

 

    //  YOUR CODE HERE

 

    return(sum);

  }

 

 

  //  PURPOSE:  To tell the number of Coin instances in '*this'.

  int getNumCoins ()

const

{ return(numCoins_); }

 

  //  VI.  Mutators:

  //  PURPOSE:  To add the Coin with address 'coinPtr' to '*this' Purse.

  //  No return value.

  void addToBack (Coin* coinPtr

  )

  {

    //  YOUR CODE HERE

  }

 

  //  PURPOSE:  To remove the Coin at the beginning of '*this' and return

  //  its address.  No parameters.

  Coin*     removeFromFront ()

  {

    Coin* returnMe = NULL;

 

    //  YOUR CODE HERE

    return(returnMe);

  }

 

 

  //  VII.  Methods that do main and misc. work of class:

  //  PURPOSE:  To print the status of '*this' Purse to 'stdout'.

  //  No parameters.  No return value.

  void print ()

const

  {

    printf

("%s has %d coins worth %d cents.\n",

getOwnerNameCPtr(),getNumCoins(),getValue()

);

  }

 

};

 

 

//  PURPOSE:  To implement a thread-safe version of Purse.

class CommonPurse : public Purse

{

  //  I.  Member vars:

  //  ADD YOUR VARIABLES HERE

 

  //  PURPOSE:  To tell the current turn.

  int turn_;

 

  //  II.  Disallowed auto-generated methods:

  //  No copy constructor:

  CommonPurse (const CommonPurse&);

 

  //  No copy assignment op:

  CommonPurse operator= (const CommonPurse&);

 

protected :

  //  III.  Protected methods:

 

public :

  //  IV.  Constructor(s), assignment op(s), factory(s) and destructor:

  //  PURPOSE:  To initialize '*this' to an empty shared Purse instance.

  CommonPurse () :

turn_(NUM_CHILDREN-1)

  {

    //  INITIALIZE YOUR VARS HERE

  }

 

  //  PURPOSE:  To release the resources of '*this'.  No parameters.

  // No return value.

  ~CommonPurse ()

  {

    //  GET RID OF YOUR VARS HERE

  }

 

 

  //  V.  Accessors:

  //  PURPOSE:  To tell the current turn.

  int getTurn ()

  const

{ return(turn_); }

 

  //  VI.  Mutators:

 

 

  //  VII.  Methods that do the main and misc. work of class:

  //  PURPOSE:  To consolidate the Coin instances of '*donorPursePtr' into

  // '*this' one.

  // (Note to the professional C++ coders: Yeah, I know it is better to use

  // call-by-reference.  I use pointers for consistency.)

  //  PUT CODE 3 PLACES IN HERE  . . . I WONDER WHERE?

  void consolidate    (Purse* donorPursePtr

)

  {

    //  I.  Application validity check:

 

    //  II.  Transfer the wealth:

 

    while  (getTurn() != donorPursePtr->getIndex())

    {

      printf

("%s: \"I want candy!  Let's put our money together!\"\n",

donorPursePtr->getOwnerNameCPtr()

);

    }

 

    while  (donorPursePtr->getNumCoins() > 0)

    {

      addToBack(donorPursePtr->removeFromFront());

    }

 

    printf

("%s: \"I added my money.\"\n",

donorPursePtr->getOwnerNameCPtr()

);

    turn_--;

 

    //  III.  Finished:

  }

  

};

 

 

//-- Global vars: --//

 

//  PURPOSE:  To represent the shared, thread-safe Purse instance.

CommonPurse sharedPurse;

 

 

//-- Main functions: --//

 

//  PURPOSE:  To add the Coin instances in '*(Purse*)vPtr' to 'sharedPurse'.

// Returns 'NULL'.

void* consolidate (void* vPtr

)

{

  Purse* pursePtr = NULL; // CHANGE THAT NULL

 

  // YOUR CODE HERE

  return(NULL);

}

 

 

//  PURPOSE:  To have the children add their money to 'sharedPurse', and

// then attempt to buy the candy.  Ignores parameters.  Returns

// 'EXIT_SUCCESS' to OS.

int main ()

{

  //  I.  Application validity check:

 

  //  II.  Try to buy candy:

  //  II.A.  Initialize data-structures:

  Purse* pursePtrArray[NUM_CHILDREN];

 

  srand(getpid());

 

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

  {

    pursePtrArray[i] = new Purse(i);

    pursePtrArray[i]->print();

  }

 

  //  II.B.  Consolidate the money:

  // YOUR CODE HERE TO START THREADS

 

  //  II.C.  Close program down:

  // YOUR CODE HERE TO WAIT FOR THREADS

 

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

  {

    delete(pursePtrArray[i]);

  }

 

  printf("All: \"We have %d cents.  ",sharedPurse.getValue());

 

  if  (sharedPurse.getValue() >= CANDY_COST)

  {

    printf("Yay!  We can afford the candy!\"\n");

  }

  else

  {

    printf("Time to beg mom for more money!\"\n");

  }

 

  //  III.  Finished:

  return(EXIT_SUCCESS);

}

    

Finish Purse:

Purse must implement a linked list of Coin instances using the Coin methods getNextPtr() and setNextPtr(). (No cheating and using C++ containers like std::list, std::vector, etc.)

 

Give class Purse 3 member variables:

A Coin* to point to the beginning of the list.

A Coin* to point to the end of the list.

An int that keeps track of the length of the list.

Initialize your variables in the constructor.

Get rid of your list in the destructor method: ~Purse(). In C one gets memory with malloc() and gives it back with free(). However, in C++ one gets memory and builds an instance of an object with new, and one dismantles the instance with delete().

Please have a local variable like coinPtr and say delete(coinPtr) for each Coin in the list.

Make getValue() loop thru the Coin instances. It should sum all the getDenomination() values of the Coin instances, and return() the sum.

Make getNumCoins() returns the how many Coin instances are in the list.

Make addToBack() add coinPtr to the back of the list. It should also increment your list-length variable.

Make removeFromFront() remove the first Coin instance from the linked list. It should also decrement your list-length variable, and return() the address of the first Coin.

Make it multi-threaded:

In main() you will need an array of NUM_CHILDREN pthread_t instances for the bee hive threads.

In section II.B declare your array variable. Have a loop that starts all NUM_CHILDREN threads. Each thread should run consolidate(), and pass the address of the corresponding Purse as an argument.

In section II.C wait for all child threads to finish.

In consolidate(), argument vPtr comes in pointing to a Purse. Set pursePtr equal to vPtr (you will need to cast it). The only thing the function needs to do is run sharedPurse.consolidate(pursePtr).

Now run it!

Make it thread-safe:

Congratulations! If you got this far you have made it multi-threaded, but not thread-safe.

To make it thread-safe you will have to add some mutex(es) and condition(s).

 

You need to protect access to the linked list and turn_ in CommonPurse method consolidate().

 

It needs one pthread_mutex_t variable and an array of NUM_CHILDREN+1 pthread_cond_t instances.

Initialize those variables in CommonPurse().

Destroy those variables in ~CommonPurse().

Use them in consolidate() in CommonPurse.

Where does the critical section begin?

Where does the critical section end?

Note: all threads should wait on the pthread_cond_t with index donorPursePtr->getIndex()+1. Also, all threads should signal the pthread_cond_t with index donorPursePtr->getIndex().

Questions:

How well did your program work before making it thread safe?

How well did your program work after making it thread safe?

 

(5/5)
Attachments:

Related Questions

. Introgramming & Unix Fall 2018, CRN 44882, Oakland University Homework Assignment 6 - Using Arrays and Functions in C

DescriptionIn this final assignment, the students will demonstrate their ability to apply two ma

. The standard path finding involves finding the (shortest) path from an origin to a destination, typically on a map. This is an

Path finding involves finding a path from A to B. Typically we want the path to have certain properties,such as being the shortest or to avoid going t

. Develop a program to emulate a purchase transaction at a retail store. This program will have two classes, a LineItem class and a Transaction class. The LineItem class will represent an individual

Develop a program to emulate a purchase transaction at a retail store. Thisprogram will have two classes, a LineItem class and a Transaction class. Th

. SeaPort Project series For this set of projects for the course, we wish to simulate some of the aspects of a number of Sea Ports. Here are the classes and their instance variables we wish to define:

1 Project 1 Introduction - the SeaPort Project series For this set of projects for the course, we wish to simulate some of the aspects of a number of

. Project 2 Introduction - the SeaPort Project series For this set of projects for the course, we wish to simulate some of the aspects of a number of Sea Ports. Here are the classes and their instance variables we wish to define:

1 Project 2 Introduction - the SeaPort Project series For this set of projects for the course, we wish to simulate some of the aspects of a number of

Ask This Question To Be Solved By Our ExpertsGet A+ Grade Solution Guaranteed

expert
Um e HaniScience

895 Answers

Hire Me
expert
Muhammad Ali HaiderFinance

889 Answers

Hire Me
expert
Husnain SaeedComputer science

962 Answers

Hire Me
expert
Atharva PatilComputer science

871 Answers

Hire Me