Answered step by step
Verified Expert Solution
Link Copied!

Question

1 Approved Answer

//Run both join and detached threads at the same time using a promise to print after the thread is complete // Include file and line

//Run both join and detached threads at the same time using a promise to print after the thread is complete // Include file and line numbers for memory leak detection for visual studio in debug mode #if defined _MSC_VER && defined _DEBUG #include  #define new new(_NORMAL_BLOCK, __FILE__, __LINE__) #define ENABLE_LEAK_DETECTION() _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF) #else #define ENABLE_LEAK_DETECTION() #endif #include  #include  #include  using namespace std; class UniformRandInt { public: void Init(int min, int max) { // Seed our random number generator with a non-deterministic random value. If no such capabilities exist then // the number will be pulled from a pseudo random number generator. randEngine.seed(randDevice()); // We want to generate values in the range of [min, max] (inclusive) with a uniform distribution. distro = std::uniform_int_distribution(min, max); } int operator()() { return distro(randEngine); } private: std::random_device randDevice; std::mt19937 randEngine; std::uniform_int_distribution distro; }; struct ThreadStruct { int id; // thread number UniformRandInt myRand; // random number generator for this thread /////////////////////////////////////////////////////////////////////////////////// // TODO:: Any new data to pass to thread should be put here /////////////////////////////////////////////////////////////////////////////////// bool* work_done; int ThreadCounter; promisepromisedWork; future futureInt; mutex* DoneMutex; mutex* CountMutex; condition_variable* CountCondition; }; /////////////////////////////////////////////////////////////////////////////////// // Prompts the user to press enter and waits for user input /////////////////////////////////////////////////////////////////////////////////// void Pause() { printf("Press enter to continue "); getchar(); } //////////////////////////////////////////////////////////////////////////////////// // TODO:: function to process (in this case just print) the 'work' // generated by the Joinable and Detached threads that were created in main. The // purpose of this function is to delay the printing of 'work' until it's been generated. // You must also print out the thread ID along with the work value. // // Note: You are required to use a std::promise to implement this logic. //////////////////////////////////////////////////////////////////////////////////// void print(ThreadStruct *threadData) { int returnValue = threadData->futureInt.get(); if(threadData->id % 2 == 0) printf("MATCHME: Joinable Thread: %d, %d, %d",threadData->id,returnValue); else { printf("MATCHME: Joinable Thread: %d, %d, %d", threadData->id, returnValue); } } /////////////////////////////////////////////////////////////////////////////////// // Entry point for joinable threads. // // Arguments: // threadData - Pointer to the thread specific data /////////////////////////////////////////////////////////////////////////////////// void JoinableThreadEntrypoint(ThreadStruct *threadData) { //////////////////////////////////////////////////////////////////////////////////// // TODO:: joinable thread to print the value of 'work' once it's generated. // The printer (or "process work") thread MUST be created before 'work' is initialized and it must not // print until 'work' has been generated by this thread. // // Note: You are required to use a std::promise to implement the printing logic. //////////////////////////////////////////////////////////////////////////////////// thread PrintThreadJoin(print, threadData); thread t(); promisepromiseInt; threadData->futureInt = promiseInt.get_future(); //future f = async(launch::async, print, threadData->futureInt,threadData); int workLimit = (threadData->id + 1) + (threadData->myRand()); int work = 0; // Performs some arbitrary amount of work. printf("START: Joinable Thread %d, starting limit = %d ", threadData->id, workLimit); for (int i = 0; i < workLimit; i += (threadData->id + 1)) { work++; } printf("FINISH: Joinable thread %d, finished with value %d ", threadData->id, work); /////////////////////////////////////////////////////////////////////////////////// // TODO:: The 'work' has been generated and the printing thread should be waiting // on the promised work to be set. Set it now so the printing thread can resume. /////////////////////////////////////////////////////////////////////////////////// promiseInt.set_value(work); PrintThreadJoin.join(); //threadData->ThreadCounter--; } /////////////////////////////////////////////////////////////////////////////////// // Entry point for detached threads. // // Arguments: // threadData - Pointer to the thread specific data /////////////////////////////////////////////////////////////////////////////////// void DetachedThreadEntrypoint(ThreadStruct *threadData) { //////////////////////////////////////////////////////////////////////////////////// // TODO:: joinable thread to print the value of 'work' once it's generated. // The printer thread MUST be created before 'work' is initialized and it must not // print until 'work' has been generated by this thread. // // Note: You are required to use a std::promise to implement the printing logic. //////////////////////////////////////////////////////////////////////////////////// thread PrintThreadDetach(print, threadData); promisepromiseInt; threadData->futureInt = promiseInt.get_future(); int workLimit = (threadData->id + 1) + (threadData->myRand()); int work = 0; printf("START: Detached Thread %d, starting limit = %d ", threadData->id, workLimit); while(true) { //////////////////////////////////////////////////////////////////////////////// // TODO:: Break out of the work loop in a thread safe way. // (HINT: thread safe means that only ONE thread should be check or modifying // shared data at a time) /////////////////////////////////////////////////////////////////////////////////// threadData->CountMutex->lock(); for (int i = 0; i < workLimit; i += (threadData->id + 1)) { work++; } // Performs some arbitrary amount of work. for (int i = 0; i < workLimit; i += (threadData->id + 1)) { work++; } threadData->CountMutex->unlock(); } printf("FINISH: Detached thread %d, finished with value %d ", threadData->id, work); /////////////////////////////////////////////////////////////////////////////////// // TODO:: Set the std::promise's value and wait for the printer thread to finish. /////////////////////////////////////////////////////////////////////////////////// promiseInt.set_value(work); PrintThreadDetach.join(); /////////////////////////////////////////////////////////////////////////////////// // TODO:: Let main know there's one less thread running. /////////////////////////////////////////////////////////////////////////////////// threadData->ThreadCounter--; } int main(int argc, char **argv) { ENABLE_LEAK_DETECTION(); if (argc != 2) { fprintf(stderr, "Usage: ThreadTypes threadCount "); fprintf(stderr, "Arguments: "); fprintf(stderr, " threadCount Number of joinable and detached threads to "); fprintf(stderr, " create. "); Pause(); return 1; } int totalThreadCount = 2 * atoi(argv[1]); if(totalThreadCount < 0) { fprintf(stderr, "Error: All arguments must be positive integer values. "); Pause(); return 1; } /////////////////////////////////////////////////////////////////////////////////// // TODO:: Declare your variables here /////////////////////////////////////////////////////////////////////////////////// vector thread_vector; ThreadStruct *perThreadData = new ThreadStruct[totalThreadCount]; printf("Main thread starting %d thread(s) ", totalThreadCount); for(int i = totalThreadCount - 1; i >= 0; i--) { perThreadData[i].id = i; perThreadData[i].myRand.Init(0, 100); /////////////////////////////////////////////////////////////////////////////////// // TODO:: Initialize any additional per-thread data and create the threads. If 'i' is // odd then the thread must execute the 'detached' logic in a detached state, otherwise // the thread must execute the 'joinable' logic. /////////////////////////////////////////////////////////////////////////////////// if (i % 2) //if i is even { //joinable thread_vector.push_back(thread(JoinableThreadEntrypoint, &perThreadData[i])); // } else { //detached thread_vector.push_back(thread(DetachedThreadEntrypoint, &perThreadData[i])); //// perThreadData->CountMutex->lock(); perThreadData->CountMutex->unlock(); //myMutex.lock(); //// //*flagPtr = true; //// //myMutex.unlock(); //// } } /////////////////////////////////////////////////////////////////////////////////// // TODO:: Wait for all joinable threads to complete /////////////////////////////////////////////////////////////////////////////////// for (thread& t : thread_vector) // { if(t.joinable()) t.join(); // } /////////////////////////////////////////////////////////////////////////////////// // TODO:: let detached threads know they need to shut down using the flag you // created in the thread structure. You may only set the flag once here (you should // not have more than one flag) and it must be in a thread safe manner. /////////////////////////////////////////////////////////////////////////////////// for (thread& t : thread_vector) // { DoneMutex.lock(); { work_done = true; } } DoneMutex.unlock(); /////////////////////////////////////////////////////////////////////////////////// // TODO:: Wait for all detached threads to finish without using a busy-wait loop. // You must wait for the number of threads to change before checking again to avoid // wasting CPU cycles. // (HINT: Remember there is a specific object that can Wait for a Condition) /////////////////////////////////////////////////////////////////////////////////// unique_lock temp(CountMutex) { CountCondition.wait(...); // fill condition } /////////////////////////////////////////////////////////////////////////////////// // TODO:: Cleanup /////////////////////////////////////////////////////////////////////////////////// Pause(); for (thread& t : thread_vector) { auto iter = find_if(thread_vector.begin(), thread_vector.end(), [=](std::thread& t) { return (t.get_id() == t.get_id()); }); if (iter != thread_vector.end()) { //iter->detach(); thread_vector.erase(iter); } } return 0; } 

Step by Step Solution

There are 3 Steps involved in it

Step: 1

blur-text-image

Get Instant Access to Expert-Tailored Solutions

See step-by-step solutions with expert insights and AI powered tools for academic success

Step: 2

blur-text-image

Step: 3

blur-text-image

Ace Your Homework with AI

Get the answers you need in no time with our AI-driven, step-by-step assistance

Get Started

Recommended Textbook for

Financial management theory and practice

Authors: Eugene F. Brigham and Michael C. Ehrhardt

12th Edition

978-0030243998, 30243998, 324422695, 978-0324422696

Students also viewed these Programming questions