Answered step by step
Verified Expert Solution
Question
1 Approved Answer
Overview: There is a farmer who wants honey. There are 4 bee hives that are willing to give honey, but want flowers in return. Cut-and-paste
-
Overview:
There is a farmer who wants honey. There are 4 bee hives that are willing to give honey, but want flowers in return. -
Cut-and-paste the following:
/*-------------------------------------------------------------------------* *--- ---* *--- hungryBees.cpp ---* */ //--- Header file inclusion: ---// #include #include #include #include #include #include //--- Definition of constants: ---// // PURPOSE: To tell how many flowers each bee hive must visit. const int NUM_FLOWERS_TO_COLLECT = 5; // PURPOSE: To tell the number of bee hives that exist. const int NUM_BEE_HIVES = 4; // PURPOSE: To hold the names of the flowers: const char* FLOWER_NAME_ARRAY[] = { "Jasmine", "Daffodil", "Daisy", "Dandelion", "Venus fly trap", "Tumbleweed", "Kudzu", "Poison Ivy" }; // PURPOSE: To tell how many flower names there are. const size_t NUM_FLOWER_NAMES= sizeof(FLOWER_NAME_ARRAY)/sizeof(const char*); //--- Definition of classes and structs: ---// // PURPOSE: To represent a flower. class Flower { // I. Member vars: // PURPOSE: To hold address of the name of the flower as a C-string. const char* nameCPtr_; // PURPOSE: To hold the address of the Flower instance after '*this' one, // or 'NULL' if there is no such Flower. Flower* nextPtr_; // II. Disallowed auto-generated methods: // No copy constructor: Flower (const Flower&); // No copy assignment op: Flower& operator= (const Flower&); protected : // III. Protected methods: public : // IV. Constructor(s), assignment op(s), factory(s) and destructor: // PURPOSE: To make '*this' a stand-alone Flower instance with a randomly- // chosen name. No parameters. No return value. Flower () : nameCPtr_(FLOWER_NAME_ARRAY[rand() % NUM_FLOWER_NAMES] ), nextPtr_(NULL) { } // PURPOSE: To release the resources of '*this'. No parameters. No // return value. ~Flower () { } // V. Accessors: // PURPOSE: To return the name of the flower. No parameters. const char* getNameCPtr () const { return(nameCPtr_); } // PURPOSE: To return the address of the Flower instance after '*this' one, // or 'NULL' if there is no such Flower. Flower* getNextPtr () const { return(nextPtr_); } // VI. Mutators: // PURPOSE: To note that the next flower in the list has address // 'newNextPtr'. No return value. void setNextPtr (Flower* newNextPtr ) { nextPtr_ = newNextPtr; } // VII. Methods that do main and misc work of class: }; class Garden { // I. Member vars: // YOUR MEMBER VARS HERE // II. Disallowed auto-created methods: // No copy constructor: Garden (const Garden&); // No copy assignment op: Garden& operator= (const Garden&); protected : // III. Protected methods: public : // IV. Constructor(s), assignment op(s), factory(s) and destructor: // PURPOSE: To initialize '*this' to an empty garden. No parameters. // No return value. Garden () { // INITIALIZE HERE } // PURPOSE: To release the resources of '*this'. No parameters. // No return value. ~Garden () { // GET RID OF LIST HERE } // V. Accessor(s): // PURPOSE: To hold length of '*this' list. int getNumFlowers () const { return(0); /* CHANGE THAT 0 */} // VI. Mutator(s): // VII. Methods that do main and misc. work of class: // PURPOSE: To add the Flower with address 'flowerPtr' at the back of // '*this' Garden of Flower instances. No return value. void store (Flower* flowerPtr ) { // ADD TO LIST HERE } // PURPOSE: To print this list of Flower instances in '*this' Garden. // No parameters. No return value. void print () { // ADD TO LIST HERE } }; struct Hive { std::string name_; Garden* gardenPtr_; Hive () : name_(""), gardenPtr_(NULL) { } ~Hive () { delete(gardenPtr_); } const char* getNameCPtr () const { return(name_.c_str()); } }; //--- Definition of global vars: ---// // PURPOSE: To hold the address of the flower offered by the farmer. // or to hold 'NULL' if there is no such Flower. Flower* availableFlowerPtr = NULL; // PURPOSE: To tell how much honey has been produced by the bee hives. int honey = 0; // YOUR CODE HERE to add global vars to control access to availableFlowerPtr and honey: //--- Definition of main functions: ---// // PURPOSE: To be the function run by the bee hive threads. 'vPtr' points // to an instance of 'Hive'. Returns 'NULL'. void* hive (void* vPtr ) { // I. Application validity check: // II. Get the flowers: // II.A. Initialize local vars: Hive* hivePtr = NULL; // CHANGE THAT NULL Garden* gardenPtr = NULL; // CHANGE THAT NULL // II.B. Each iteration obtains another Flower instance for the graden // of Hive '*hivePtr': while (gardenPtr->getNumFlowers() < NUM_FLOWERS_TO_COLLECT) { // YOUR CODE HERE: Make access to avaialbleFlowerPtr thread-safe while (availableFlowerPtr == NULL) { printf("%s: \"Hey! No flowers, no honey!\" ",hivePtr->getNameCPtr()); } printf("%s: \"A %s! Sure we will take that!\" ", hivePtr->getNameCPtr(),availableFlowerPtr->getNameCPtr() ); gardenPtr->store(availableFlowerPtr); availableFlowerPtr = NULL; // Leave this outside critical section: sleep(rand() % 3); // Please leave this OUT of the critical section } // II.C. Add to the honey when have enough flowers: printf("%s \"Finally, enough flowers to make some honey.\" ", hivePtr->getNameCPtr() ); // YOUR CODE HERE: Make incrementing honey thread-save honey++; // III. Finished: return(NULL); } // PURPOSE: To be the function run by the farmer thread. 'vPtr' is ignored. // Returns 'NULL'. void* farmer (void* vPtr) { // I. Application validity check: // II. Give flowers: // II.A. Each iteration creates and gives another Flower instance // until there is sufficient honey: while (true) { // YOUR CODE HERE: Make access to honey thread-safe if (honey >= NUM_BEE_HIVES) { break; } printf("Farmer: \"I have to gather *more* flowers?!?\" "); // YOUR CODE HERE: Make access to availableFlowerPtr thread-safe while (availableFlowerPtr != NULL) { printf("Farmer: \"Hey, you said you wanted" " a flower, come and take it.\" " ); } availableFlowerPtr = new Flower; printf("Farmer: \"Okay here is another flower: a %s\" ", availableFlowerPtr->getNameCPtr() ); // Leave this outside critical section: sleep(rand() % 3); // Please leave this OUT of the critical section } // III. Finished: printf("Farmer \"I *finally* got my honey!\" "); return(NULL); } // PURPOSE: To run the program. Ignores command line arguments. Returns // 'EXIT_SUCCESS' to OS. int main () { // I. Application validity check: // II. Have the farmer give Flower instances until sufficient honey // has been obtained: // II.A. Randomize random number generator: srand(getpid()); // II.B. Initialize global vars: Hive hiveArray[NUM_BEE_HIVES]; // Add something here? // II.C. Make threads: // II.C.1. Make bee hive threads: for (int i = 0; i < NUM_BEE_HIVES; i++) { hiveArray[i].name_ = std::string("Hive ") + (char)('A'+i); hiveArray[i].gardenPtr_ = new Garden; // Add something here? } // II.C.2. Make farmer thread: // Add something here? // II.D. Wait for child threads: // II.D.1. Wait for bee hive threads: for (int i = 0; i < NUM_BEE_HIVES; i++) { // Add something here? printf("%s has: ",hiveArray[i].getNameCPtr()); hiveArray[i].gardenPtr_->print(); } // II.D.2. Wait for farmer thread: // Add something here? // II.E. Get rid of global vars: // Add something here? // III. Finished: return(EXIT_SUCCESS); }
-
Finish Garden:
Garden must implement a linked list of Flower instances using the Flower methods getNextPtr() and setNextPtr(). (No cheating and using C++ containers likestd::list, std::vector, etc.)
- Give class Garden 3 member variables:
- A Flower* to point to the beginning of the list.
- A Flower* 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: ~Garden(). 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 flowerPtr and say delete(flowerPtr) for each Flower in the list.
- Make getNumFlowers() return the how many Flower instances are in the list.
- Make store() add new Flower instance flowerPtr to the end of the list.
- Make print() print the Flower instances in the list.
- Give class Garden 3 member variables:
-
Make it multi-threaded:
- In main() you will need a single pthread_t for the farmer thread, and an array of NUM_BEE_HIVES pthread_t instances for the bee hive threads.
- Declare your variables in section II.B.
- Start your threads in section II.C. The bee hive threads should run hive() with the address of hiveArray[i] passed to them. The farmer thread should run farmer(). Just pass NULL as the argument to farmer().
- In section II.D wait for all child threads to finish.
- In hive(), argument vPtr comes in pointing to a Hive. Set hivePtr equal to vPtr (you will need to cast it), and set gardenPtr equal to the address of the Garden owned by the Hive. (See struct Hive.)
- Now run it!
- In main() you will need a single pthread_t for the farmer thread, and an array of NUM_BEE_HIVES pthread_t instances for the bee hive threads.
-
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 two variables:
- availableFlowerPtr, under Definition of global vars:. This one acts like a one-element buffer.
- The farmer thread has to wait while it has a non-NULL value ("is-full").
- The bee hive threads have to wait while it has a NULL value ("is-empty").
- honey, also under Definition of global vars:. Unlike availableFlowerPtr, there is no need to wait to use this variable.
Stop! Think! What needs mutexes? What needs conditions?
- Declare your variables globally in the Definition of global vars: section
- Initialize those variables in main() in section II.B.
- Destroy those variables in main() in section II.E.
- Use them in farmer to protect access to both honey and availableFlowerPtr.
- Use them in hive to protect access to both availableFlowerPtr and honey.
- availableFlowerPtr, under Definition of global vars:. This one acts like a one-element buffer.
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