Multi-core Programming Destroy the Castle Lab 4 Code snippets
2 Lab 4 Activity 1 Steps 2-5 Declare ThreadContext structure //////////////////////////////////////////////////////////////////////////// ///Lab 4 Activity 1: Declare ThreadContext structure /// /// /// Declare a wrapper class for Win32 threads. Each instance's tick() /// /// function copies thread local data and wakes up the thread by issuing /// /// a SetEvent() call. /// /// 1) As part of the lab, uncomment the macro definition for /// /// THREADCONTEXT_EVENTS_DECLARED /// /// 2) Add a declaration for the Thread handle (m_thread) /// /// 3) Add declarations for the Start and Done event handles (m_evtStart /// /// and m_evtDone) /// /// /// INSERT CODE HERE /// #define THREADCONTEXT_EVENTS_DECLARED HANDLEm_evtStart; HANDLEm_evtDone; HANDLEm_thread;
3 Lab 4 Activity 1 Steps 6-7 Create and Init ThreadContext array ///////////////////////////////////////////////////////////////////////////// /// /// ///Lab 4 Activity 1: Create and Initialize ThreadContext array /// /// /// 1) Create an instance of the ThreadContext wrapper class for each of /// /// the Win32 threads. /// /// 2) 'init'ialize each ThreadContext structure /// /// 3) Push a shared pointer to each ThreadContext onto the m_contexts /// /// vector. /// /// INSERT CODE HERE /// for (int i=0; i<num_threads; i++) { ThreadContextPtr cp(new ThreadContext(this, i)); if (!cp->init()) break; m_contexts.push_back(cp); }
4 Lab 4 Activity 1 Step 8 Initialize ThreadContext /////////////////////////////////////////////////////////////////////////// ///Lab 4 Activity 1: Initialize ThreadContext /// /// /// 1) Create Start and Done events used to signal the worker threads /// /// 2) Create a Win32 Thread using _beginthreadex() with a 5K stack set /// /// with entry point as _WorkerThreadProc /// /// /// INSERT CODE HERE /// m_evtStart=::CreateEvent(0, FALSE, FALSE, 0 ); m_evtDone=::CreateEvent(0, FALSE, FALSE, 0 ); if (m_evtDone!=0 && m_evtStart!=0) { m_thread=(HANDLE)::_beginthreadex(NULL, 512*1024, _WorkerThreadProc, this, 0, NULL ); if (m_thread!=0 && m_thread!=INVALID_HANDLE_VALUE) { return true; }
5 Lab 4 Activity 2 Steps 1-4 Divide data and notify Worker threads //////////////////////////////////////////////////////////////////////////// /// Split the AI Workload to available threads and issue a SetEvent() to /// /// let the worker threads start processing. This tick() function will /// /// wait till the worker threads' tick() functions complete. /// /// /// 1) Split getNumMOBS() amount of work between 'threads'. /// /// 2) Loop through and call the Workers' tick() functions using the /// /// ThreadContext vector with the specified chunk of data. /// /// 3) Finally, wait for all Worker threads to finish using a /// /// WaitForMultipleObjects() call. /// for (unsigned i=0; i<threads; i++) { unsigned from=i*blkSize; unsigned to=from+blkSize; if (to>=getNumMOBS()) to=getNumMOBS(); m_contexts[i]->tick(from, to, currentTime, elapsedTime ); threadEvents[i]=m_contexts[i]->getDoneEvent(); } ::WaitForMultipleObjects(threads, threadEvents, TRUE, INFINITE);
6 Lab 4 Activity 2 Steps 5-7 Implement Worker thread tick function /////////////////////////////////////////////////////////////////////////// /// /// ///Lab 4 Activity 2: Implement Worker thread function /// /// /// This function will wait till a Start event signal from the main AI /// /// thread, and then call the DemoEngine's tick with the given slice of /// /// data. /// ///1) Wait for m_evtStart event /// ///2) Check m_stopped to see if the AI DemoEngine is halted /// ///3) Issue the DemoEngine tick to handle the subset of data. /// ///4) SetEvent m_evtDone to let the main AIThread know we're done /// /// /// INSERT CODE HERE /// ::WaitForSingleObject(m_evtStart, INFINITE); if (m_stopped) break; m_engine->tick(m_from, m_to, m_currentTime,m_elapsedTime); ::SetEvent(m_evtDone);