//***************************************************************************************/ // // File name: Dispatcher.cpp // Location: ...\Matrox Imaging\MILxxx\Examples\Processing\Optimization\MultiProcessing\C++ // // // Synopsis: Implements the CDispatcher class. // // Copyright (C) Matrox Electronic Systems Ltd., 1992-2015. // All Rights Reserved #include "common.h" //******************************************************************************* // Constructor. Allocates and initializes the dispatcher //******************************************************************************* CDispatcher::CDispatcher(MIL_ID MilSystem, PROC_FUNCTION_PTR ProcessingFunctionPtr, void* DataPtr) : m_MilSystem(MilSystem), m_ProcessingFunctionPtr(ProcessingFunctionPtr), m_DataPtr(DataPtr), m_ThreadStarted(false), m_DispatchRunning(false), m_FrameRate(0.0) { } //******************************************************************************* // Destructor. Frees the dispatcher objects. //******************************************************************************* CDispatcher::~CDispatcher() { StopThread(); } //******************************************************************************* // StartThread. Start the dispatcher thread. Initially the thread is paused. //******************************************************************************* void CDispatcher::StartThread() { if (!m_ThreadStarted) { //Allocate the dispatcher thread and events MthrAlloc (m_MilSystem, M_EVENT, M_NOT_SIGNALED+M_AUTO_RESET, M_NULL, M_NULL, &m_MilEvents[enRun]); MthrAlloc (m_MilSystem, M_EVENT, M_NOT_SIGNALED+M_AUTO_RESET, M_NULL, M_NULL, &m_MilEvents[enKill]); MthrAlloc (m_MilSystem, M_EVENT, M_NOT_SIGNALED+M_AUTO_RESET, M_NULL, M_NULL, &m_MilDispatchStoppedEvent); //Allocate a thread, it is initially paused. MthrAlloc (m_MilSystem, M_THREAD, M_DEFAULT, &DispatchFunction, (void*)this, &m_MilDispatchThread); m_ThreadStarted = true; } } //******************************************************************************* // StopThread. Stop the thread and free related events. //******************************************************************************* void CDispatcher::StopThread() { if (m_ThreadStarted) { //Stop the thread Pause(); MthrControl(m_MilEvents[enKill], M_EVENT_SET, M_SIGNALED); //Free related objects MthrWait(m_MilDispatchThread, M_THREAD_END_WAIT, M_NULL); MthrFree(m_MilEvents[enRun]); MthrFree(m_MilEvents[enKill]); MthrFree(m_MilDispatchStoppedEvent); MthrFree(m_MilDispatchThread); m_ThreadStarted = false; } } //******************************************************************************* // Run. Runs the processing in the dispatch thread. //******************************************************************************* void CDispatcher::Run() { if (!m_DispatchRunning && m_ThreadStarted) { m_DispatchRunning = true; //Signal to start processing MthrControl(m_MilEvents[enRun], M_EVENT_SET, M_SIGNALED); } } //******************************************************************************* // Pause. Pauses the processing in the dispatch thread. //******************************************************************************* void CDispatcher::Pause() { if (m_DispatchRunning) { //Signal to stop the processing m_DispatchRunning = false; //Wait for the dispatching to stop MthrWait(m_MilDispatchStoppedEvent, M_EVENT_WAIT, M_NULL); m_FrameRate = 0.0; } } //******************************************************************************* // RunDispatcher. Function called in DispatchFunction to copy the buffer and // manage the call to the user function. //******************************************************************************* void CDispatcher::RunDispatcher() { const MIL_INT UpdateInterval = 2; MIL_DOUBLE EndTime; MIL_INT NumFrames=0; MIL_DOUBLE TotalTime; MIL_DOUBLE PreviousUpdateTime = 0.0; m_FrameRate = 0; //Wait for an event while ( MthrWaitMultiple(m_MilEvents, NUM_EVENTS, M_EVENT_WAIT, M_NULL) != (MIL_INT)enKill ) { MappTimer(M_TIMER_READ, &PreviousUpdateTime); //Call and benchmark the processing function while the stop signal has not been received while (m_DispatchRunning) { //Call the processing function m_ProcessingFunctionPtr(m_DataPtr); MthrWait(M_DEFAULT, M_THREAD_WAIT, M_NULL); //Time the processing and calculate the FPS NumFrames++; MappTimer(M_TIMER_READ, &EndTime); if ((EndTime-PreviousUpdateTime)>UpdateInterval) { TotalTime = EndTime-PreviousUpdateTime; m_FrameRate = NumFrames / TotalTime; NumFrames = 0; PreviousUpdateTime=EndTime; } } //Signal that the dispatcher has stopped MthrControl(m_MilDispatchStoppedEvent, M_EVENT_SET, M_SIGNALED); } } //******************************************************************************* // DispatchFunction. Call back function for the dispatch thread. //******************************************************************************* MIL_UINT32 MFTYPE CDispatcher::DispatchFunction(void *UserDataPtr) { CDispatcher* Dispatcher = (CDispatcher*)UserDataPtr; //Run the dispatcher Dispatcher->RunDispatcher(); return 0; }