Question
***UTILIZING C++*** buyTheCandy.cpp Overview: A package of 4 candy candies cost 100 cents. (It can be 1 USD, 1 Euro, 1 whatever). Four siblings (brothers
***UTILIZING C++***
buyTheCandy.cpp
Overview:
A package of 4 candy candies cost 100 cents. (It can be 1 USD, 1 Euro, 1 whatever). Four siblings (brothers or sisters) want a candy, and each has some money. Unfortunately, probably none of the siblings has enough money to buy the candies by themself. So they will all pool their money and jointly buy the candy.
There are 3 classes:
Coin: Represents some money
Purse: Implements a container (a linked list) of Coin instances.
CommonPurse: a thread-safe version of Purse
Each sibling has their money in a Purse instance. Additionally, there is a CommonPurse called sharedPurse to which all siblings will add their money. Because each sibling is implemented with its own thread, the individual Purse instances do not need to be thread safe. However, sharedPurse needs to be made thread-safe because all four threads can access it.
Cut-and-paste the following:
/*-------------------------------------------------------------------------* *--- ---* *--- buyTheCandy.cpp ---* *--- ---* *--- This file defines a program that exercises linked list and ---* *--- threading skills by simulating 4 children pooling their money ---* *--- to buy a pack of candy. ---* *--- ---* *--- ---- ---- ---- ---- ---- ---- ---- ---- ---* *--- ---* *--- ---* *--- ---* *-------------------------------------------------------------------------*/ /* * $ g++ -lpthread -g buyTheCandy.cpp -o buyTheCandy */ //-- Standard inclusions: --// #include#include #include #include //-- 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 // 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. ", 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!\" ", donorPursePtr->getOwnerNameCPtr() ); } while (donorPursePtr->getNumCoins() > 0) { addToBack(donorPursePtr->removeFromFront()); } printf ("%s: \"I added my money.\" ", 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 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 = CANDY_COST) { printf("Yay! We can afford the candy!\" "); } else { printf("Time to beg mom for more money!\" "); } // III. Finished: return(EXIT_SUCCESS); }
A. 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.)
1. 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.
2. Initialize your variables in the constructor.
3. 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.
4. Make getValue() loop thru the Coin instances. It should sum all the getDenomination() values of the Coin instances, and return() the sum.
5. Make getNumCoins() returns the how many Coin instances are in the list.
6. Make addToBack() add coinPtr to the back of the list. It should also increment your list-length variable.
7. 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.
B. Make it multi-threaded:
1. 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.
2. 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).
3. Now run it!
Sample ouput:
Please show screenshots of output!
Thank you!
$./buyTheCandy Alice has 4 coins worth 41 cents. Bob has 4 coins worth 50 cents. Cathy has 4 coins worth 16 cents. David has 4 coins worth 50 cents. Bob: "I want candy! Let's put our money together!" Cathy: "I want candy! Let's put our money together!" David: "I added my money." Alice: "I want candy! Let's put our money together!" Cathy: "I added my money." Bob: "I added my money. Alice: "I added my money." All: "We have 157 cents. Yay! We can afford the candy!" $./buyTheCandy Alice has 4 coins worth 12 cents. Bob has 4 coins worth 36 cents. Cathy has 4 coins worth 8 cents. David has 4 coins worth 16 cents. Alice: "I want candy! Let's put our money together!" Cathy: "I want candy! Let's put our money together!" Bob: "I want candy! Let's put our money together!" David: "I added my money." Cathy: "I added my money." Bob: "I added my money." Alice: "I added my money." All: "We have 72 cents. Time to beg mom for more money!" \$./buyTheCandy Alice has 4 coins worth 37 cents. Bob has 4 coins worth 22 cents. Cathy has 4 coins worth 80 cents. David has 4 coins worth 21 cents. Alice: "I want candy! Let's put our money together!" Bob: "I want candy! Let's put our money together!" David: "I added my money." Cathy: "I added my money." Bob: "I added my money. Alice: "I added my money." All: "We have 160 cents. Yay! We can afford the candy
Step by Step Solution
There are 3 Steps involved in it
Step: 1
Get Instant Access to Expert-Tailored Solutions
See step-by-step solutions with expert insights and AI powered tools for academic success
Step: 2
Step: 3
Ace Your Homework with AI
Get the answers you need in no time with our AI-driven, step-by-step assistance
Get Started