📄 timedeventcaller.cpp
字号:
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft shared
// source or premium shared source license agreement under which you licensed
// this source code. If you did not accept the terms of the license agreement,
// you are not authorized to use this source code. For the terms of the license,
// please see the license agreement between you and Microsoft or, if applicable,
// see the SOURCE.RTF on your install media or the root of your tools installation.
// THE SOURCE CODE IS PROVIDED "AS IS", WITH NO WARRANTIES.
//
#include "av_upnp.h"
using namespace av_upnp;
using namespace av_upnp::details;
/////////////////////////////////////////////////////////////////////////////
// TimedEventCaller
DWORD TimedEventCaller::RegisterCallee(DWORD nTimeout, ITimedEventCallee* pCallee)
{
if(!pCallee)
return ERROR_AV_POINTER;
ce::gate<ce::critical_section_with_copy> gate(m_csMapCalleeGroups);
CalleeGroupMap::iterator it = m_mapCalleeGroups.find(nTimeout);
if(it == m_mapCalleeGroups.end())
{
// Create CalleeGroup for this timeout
it = m_mapCalleeGroups.insert(nTimeout, CalleeGroup(nTimeout));
if(it == m_mapCalleeGroups.end())
return ERROR_AV_OOM;
}
return it->second.RegisterCallee(pCallee);
}
DWORD TimedEventCaller::UnregisterCallee(DWORD nTimeout, ITimedEventCallee* pCallee)
{
if(!pCallee)
return ERROR_AV_POINTER;
ce::gate<ce::critical_section_with_copy> gate(m_csMapCalleeGroups);
const CalleeGroupMap::iterator it = m_mapCalleeGroups.find(nTimeout);
if(it == m_mapCalleeGroups.end())
return ERROR_AV_INVALID_INSTANCE;
if(it->second.UnregisterCallee(pCallee))
{
// erase empty callee group
m_mapCalleeGroups.erase(it);
}
return SUCCESS_AV;
}
void TimedEventCaller::AddRef(DWORD nTimeout)
{
ce::gate<ce::critical_section_with_copy> gate(m_csMapCalleeGroups);
CalleeGroupMap::iterator it = m_mapCalleeGroups.find(nTimeout);
assert(it != m_mapCalleeGroups.end());
it->second.AddRef();
}
void TimedEventCaller::Release(DWORD nTimeout)
{
ce::gate<ce::critical_section_with_copy> gate(m_csMapCalleeGroups);
CalleeGroupMap::iterator it = m_mapCalleeGroups.find(nTimeout);
assert(it != m_mapCalleeGroups.end());
it->second.Release();
}
//
// EventCallerThread
//
DWORD WINAPI TimedEventCaller::CalleeGroup::EventCallerThread(LPVOID lpvthis)
{
assert(lpvthis);
// This function loops on the for statement every pThis->m_nTimeout ms to call the callees,
// also waking up when it has been signaled to exit. If m_hEventRun is not signaled,
// it blocks until m_hEventRun is again signaled or this thread has been signaled to exit.
CalleeGroup* pThis = reinterpret_cast<CalleeGroup*>(lpvthis);
HANDLE aEvents[] = {pThis->m_hEventRun, pThis->m_hEventExit};
for(;;)
{
DWORD dw;
if(WAIT_TIMEOUT != (dw = WaitForSingleObject(pThis->m_hEventExit, pThis->m_nTimeout)))
{
assert(dw == WAIT_OBJECT_0);
return 0;
}
if(WAIT_OBJECT_0 == (dw = WaitForMultipleObjects(sizeof(aEvents)/sizeof(aEvents[0]), aEvents, FALSE, INFINITE)))
{
ce::gate<ce::critical_section_with_copy> gate(pThis->m_cs);
for(CalleeSet::iterator it = pThis->m_setCallees.begin(), itEnd = pThis->m_setCallees.end(); itEnd != it; ++it)
(*it)->TimedEventCall();
}
else
assert(dw == WAIT_OBJECT_0 + 1);
}
}
/////////////////////////////////////////////////////////////////////////////
// CalleeGroup
TimedEventCaller::CalleeGroup::CalleeGroup(DWORD nTimeout)
: m_nTimeout(nTimeout),
m_nRefs(0)
{
}
TimedEventCaller::CalleeGroup::~CalleeGroup()
{
assert(m_setCallees.empty());
}
// RegisterCallee
DWORD TimedEventCaller::CalleeGroup::RegisterCallee(ITimedEventCallee* pCallee)
{
ce::gate<ce::critical_section_with_copy> gate(m_cs);
assert(m_setCallees.end() == m_setCallees.find(pCallee));
if(m_setCallees.end() == m_setCallees.insert(pCallee))
return ERROR_AV_OOM;
if(1 == m_setCallees.size())
{
assert(!m_hEventRun.valid());
assert(!m_hEventExit.valid());
m_hEventRun = CreateEvent(NULL, TRUE, FALSE, NULL);
m_hEventExit = CreateEvent(NULL, TRUE, FALSE, NULL);
if(!m_hEventRun.valid() || !m_hEventExit.valid())
{
m_setCallees.erase(pCallee);
return ERROR_AV_OOM;
}
// Create the thread for this no-longer-callee-empty CalleeGroup
m_hCallerThread = CreateThread(NULL,
0,
TimedEventCaller::CalleeGroup::EventCallerThread,
static_cast<LPVOID>(this),
0,
NULL);
if(!m_hCallerThread.valid())
{
m_setCallees.erase(pCallee);
return ERROR_AV_UPNP_ACTION_FAILED;
}
}
return SUCCESS_AV;
}
// UnregisterCallee
BOOL TimedEventCaller::CalleeGroup::UnregisterCallee(ITimedEventCallee* pCallee)
{
ce::gate<ce::critical_section_with_copy> gate(m_cs);
size_t nItemsErased = m_setCallees.erase(pCallee);
assert(nItemsErased);
if(0 == m_setCallees.size())
{
// must leave lock as EventCallerThread() may need to obtain this lock before exiting
gate.leave();
assert(m_hEventExit.valid());
assert(m_hCallerThread.valid());
BOOL bRet = SetEvent(m_hEventExit);
assert(bRet);
DWORD dw = WaitForSingleObject(m_hCallerThread, INFINITE);
assert(dw == WAIT_OBJECT_0);
return TRUE;
}
return FALSE;
}
// AddRef
void TimedEventCaller::CalleeGroup::AddRef()
{
assert(ULONG_MAX != m_nRefs);
if(1 == InterlockedIncrement(&m_nRefs))
SetEvent(m_hEventRun);
}
// Release
void TimedEventCaller::CalleeGroup::Release()
{
assert(m_nRefs > 0);
LONG refCnt = InterlockedDecrement(&m_nRefs);
if(0 == refCnt)
ResetEvent(m_hEventRun);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -