Path: blob/master/samples/winrt/ImageManipulations/MediaExtensions/Common/OpQueue.h
16354 views
//////////////////////////////////////////////////////////////////////////1//2// OpQueue.h3// Async operation queue.4//5// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF6// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO7// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A8// PARTICULAR PURPOSE.9//10// Copyright (c) Microsoft Corporation. All rights reserved.11//12//////////////////////////////////////////////////////////////////////////1314#pragma once1516#pragma warning( push )17#pragma warning( disable : 4355 ) // 'this' used in base member initializer list1819/*20This header file defines an object to help queue and serialize21asynchronous operations.2223Background:2425To perform an operation asynchronously in Media Foundation, an object26does one of the following:27281. Calls MFPutWorkItem(Ex), using either a standard work queue29identifier or a caller-allocated work queue. The work-queue30thread invokes the object's callback.31322. Creates an async result object (IMFAsyncResult) and calls33MFInvokeCallback to invoke the object's callback.3435Ultimately, either of these cause the object's callback to be invoked36from a work-queue thread. The object can then complete the operation37inside the callback.3839However, the Media Foundation platform may dispatch async callbacks in40parallel on several threads. Putting an item on a work queue does NOT41guarantee that one operation will complete before the next one starts,42or even that work items will be dispatched in the same order they were43called.4445To serialize async operations that should not overlap, an object should46use a queue. While one operation is pending, subsequent operations are47put on the queue, and only dispatched after the previous operation is48complete.4950The granularity of a single "operation" depends on the requirements of51that particular object. A single operation might involve several52asynchronous calls before the object dispatches the next operation on53the queue.545556*/57585960//-------------------------------------------------------------------61// OpQueue class template62//63// Base class for an async operation queue.64//65// TOperation: The class used to describe operations. This class must66// implement IUnknown.67//68// The OpQueue class is an abstract class. The derived class must69// implement the following pure-virtual methods:70//71// - IUnknown methods (AddRef, Release, QI)72//73// - DispatchOperation:74//75// Performs the asynchronous operation specified by pOp.76//77// At the end of each operation, the derived class must call78// ProcessQueue to process the next operation in the queue.79//80// NOTE: An operation is not required to complete inside the81// DispatchOperation method. A single operation might consist82// of several asynchronous method calls.83//84// - ValidateOperation:85//86// Checks whether the object can perform the operation specified87// by pOp at this time.88//89// If the object cannot perform the operation now (e.g., because90// another operation is still in progress) the method should91// return MF_E_NOTACCEPTING.92//93//-------------------------------------------------------------------94#include "linklist.h"95#include "AsyncCB.h"9697template <class T, class TOperation>98class OpQueue //: public IUnknown99{100public:101102typedef ComPtrList<TOperation> OpList;103104HRESULT QueueOperation(TOperation *pOp);105106protected:107108HRESULT ProcessQueue();109HRESULT ProcessQueueAsync(IMFAsyncResult *pResult);110111virtual HRESULT DispatchOperation(TOperation *pOp) = 0;112virtual HRESULT ValidateOperation(TOperation *pOp) = 0;113114OpQueue(CRITICAL_SECTION& critsec)115: m_OnProcessQueue(static_cast<T *>(this), &OpQueue::ProcessQueueAsync),116m_critsec(critsec)117{118}119120virtual ~OpQueue()121{122}123124protected:125OpList m_OpQueue; // Queue of operations.126CRITICAL_SECTION& m_critsec; // Protects the queue state.127AsyncCallback<T> m_OnProcessQueue; // ProcessQueueAsync callback.128};129130131132//-------------------------------------------------------------------133// Place an operation on the queue.134// Public method.135//-------------------------------------------------------------------136137template <class T, class TOperation>138HRESULT OpQueue<T, TOperation>::QueueOperation(TOperation *pOp)139{140HRESULT hr = S_OK;141142EnterCriticalSection(&m_critsec);143144hr = m_OpQueue.InsertBack(pOp);145if (SUCCEEDED(hr))146{147hr = ProcessQueue();148}149150LeaveCriticalSection(&m_critsec);151return hr;152}153154155//-------------------------------------------------------------------156// Process the next operation on the queue.157// Protected method.158//159// Note: This method dispatches the operation to a work queue.160//-------------------------------------------------------------------161162template <class T, class TOperation>163HRESULT OpQueue<T, TOperation>::ProcessQueue()164{165HRESULT hr = S_OK;166if (m_OpQueue.GetCount() > 0)167{168hr = MFPutWorkItem2(169MFASYNC_CALLBACK_QUEUE_STANDARD, // Use the standard work queue.1700, // Default priority171&m_OnProcessQueue, // Callback method.172nullptr // State object.173);174}175return hr;176}177178179//-------------------------------------------------------------------180// Process the next operation on the queue.181// Protected method.182//183// Note: This method is called from a work-queue thread.184//-------------------------------------------------------------------185186template <class T, class TOperation>187HRESULT OpQueue<T, TOperation>::ProcessQueueAsync(IMFAsyncResult *pResult)188{189HRESULT hr = S_OK;190TOperation *pOp = nullptr;191192EnterCriticalSection(&m_critsec);193194if (m_OpQueue.GetCount() > 0)195{196hr = m_OpQueue.GetFront(&pOp);197198if (SUCCEEDED(hr))199{200hr = ValidateOperation(pOp);201}202if (SUCCEEDED(hr))203{204hr = m_OpQueue.RemoveFront(nullptr);205}206if (SUCCEEDED(hr))207{208(void)DispatchOperation(pOp);209}210}211212if (pOp != nullptr)213{214pOp->Release();215}216217LeaveCriticalSection(&m_critsec);218return hr;219}220221#pragma warning( pop )222223224