//+------------------------------------------------------------------------- // // Microsoft Windows // // Copyright (C) Microsoft Corporation, 2000 - 2000 // // File: eventlock.h // // This file contains code needed to fire script event in a safer way // Locks made on stack will postpone firing the event on particular interface // as long as the last lock is released. //-------------------------------------------------------------------------- #pragma once #if !defined(EVENTLOCK_H_INCLUDED) #define EVENTLOCK_H_INCLUDED #include #include "baseapi.h" /***************************************************************************\ * * CLASS: CEventBuffer * * PURPOSE: objects this class maintains the interface locks by exposing * methods Lock(), Unlock() and IsLocked(); It also implements queue * of script events accessible thru ScEmitOrPostpone(); Events in the queue * will be automatically emited when the last lock is removed by * calling Unlock() method. * * USAGE: Object of this class are constucted as global or static variables * per each monitored interface. * Currently it is used (as static variable) by GetEventBuffer template * function and is accessed by CEventLock object put on the stack by * LockComEventInterface macro * \***************************************************************************/ class MMCBASE_API CEventBuffer { // structure containing postponed script event // since it is a dipinterface call, data consists of pointer to // IDispatch interface , disp_id and the array of parameters struct DispCallStr { IDispatchPtr spDispatch; DISPID dispid; std::vector vars; }; // the following member is not used from anywhere else but from mmcbase.dll - based methods // thus it is safe to have it here ( but we need to silence the warning ) #pragma warning(disable:4251) // queue of postponed events std::queue m_postponed; #pragma warning(default:4251) // lock count int m_locks; public: // constructor. No locks initially CEventBuffer(); ~CEventBuffer(); // locking methods void Lock() { m_locks++; } void Unlock() { ASSERT(m_locks > 0); if (--m_locks == 0) ScFlushPostponed(); } bool IsLocked() { return m_locks != 0; } // event emitting / postponing SC ScEmitOrPostpone(IDispatch *pDispatch, DISPID dispid, CComVariant *pVar, int count); private: // helper emiting postponed events SC ScFlushPostponed(); }; /***************************************************************************\ * * FUNCTION: GetEventBuffer * * PURPOSE: This function provides access to static object created in it's body * Having it as template allows us to define as many static objects as * interfaces we have. * * PARAMETERS: * * RETURNS: * CEventBuffer& - reference to the static object created inside * \***************************************************************************/ MMCBASE_API CEventBuffer& GetEventBuffer(); /***************************************************************************\ * * CLASS: CEventLock * * PURPOSE: Template class to allow simple Lock()/Unlock() functionality * by placing instances of this class on the stack. * Constructor will put a lock on the event interface, destructor * will release it. * * USAGE: You can place the lock on stack by constructing object directly * or by using LockComEventInterface macro (which does the same) * \***************************************************************************/ template class MMCBASE_API CEventLock { public: CEventLock() { GetEventBuffer().Lock(); } ~CEventLock() { GetEventBuffer().Unlock(); } }; /***************************************************************************\ * * MACRO: LockComEventInterface * * PURPOSE: Constructs the object on stack which holds a lock on event interface * \***************************************************************************/ #define LockComEventInterface(_dispinterface) \ CEventLock<_dispinterface> _LocalEventInterfaceLock; #endif // !defined(EVENTLOCK_H_INCLUDED)