DragonNest/Third/XTToolkitPro/Source/Common/XTPNotifyConnection.cpp

343 lines
7.9 KiB
C++
Raw Normal View History

2024-12-19 09:48:26 +08:00
// XTPNotifyConnection.cpp: implementation of the CXTPNotifyConnection and CXTPNotifySink classes.
//
// This file is a part of the XTREME TOOLKIT PRO MFC class library.
// (c)1998-2008 Codejock Software, All Rights Reserved.
//
// THIS SOURCE FILE IS THE PROPERTY OF CODEJOCK SOFTWARE AND IS NOT TO BE
// RE-DISTRIBUTED BY ANY MEANS WHATSOEVER WITHOUT THE EXPRESSED WRITTEN
// CONSENT OF CODEJOCK SOFTWARE.
//
// THIS SOURCE CODE CAN ONLY BE USED UNDER THE TERMS AND CONDITIONS OUTLINED
// IN THE XTREME TOOLKIT PRO LICENSE AGREEMENT. CODEJOCK SOFTWARE GRANTS TO
// YOU (ONE SOFTWARE DEVELOPER) THE LIMITED RIGHT TO USE THIS SOFTWARE ON A
// SINGLE COMPUTER.
//
// CONTACT INFORMATION:
// support@codejock.com
// http://www.codejock.com
//
/////////////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "XTPNotifyConnection.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
#pragma warning(disable: 4571) // warning C4571: catch(...) blocks compiled with /EHs do not catch or re-throw Structured Exceptions
/////////////////////////////////////////////////////////////////////////////
static LPCTSTR XTP_NOTIFICATION_SINK_MT_MSGWND_NAME = _T("XTPNotificationSinkMT_MsgWnd");
/////////////////////////////////////////////////////////////////////////////
//class CEmptySyncObject : public CSyncObject
CXTPNotifyConnection::CEmptySyncObject::CEmptySyncObject() :
CSyncObject(_T("XTPEmptySyncObject"))
{
}
////////////////////////////////////////////////////////////////////////////
CXTPNotifyConnection::CXTPNotifyConnection()
{
m_nSendQueueCacheSize = 0;
}
CXTPNotifyConnection::~CXTPNotifyConnection()
{
RemoveAll();
}
void CXTPNotifyConnection::RemoveAll()
{
CSingleLock singleLock(GetDataLock(), TRUE);
int nCount = (int)m_arrConnections.GetSize();
for (int i = 0; i < nCount; i++)
{
CONNECTION_DESCRIPTOR* pCurElem = m_arrConnections[i];
ASSERT(pCurElem);
if (pCurElem)
{
delete pCurElem;
}
m_arrConnections[i] = NULL;
}
m_arrConnections.RemoveAll();
}
XTP_CONNECTION_ID CXTPNotifyConnection::Advise(XTP_NOTIFY_CODE Event, CXTPNotifySink* pSink)
{
ASSERT(pSink);
CSingleLock singleLock(GetDataLock(), TRUE);
CONNECTION_DESCRIPTOR* pNewElem = new CONNECTION_DESCRIPTOR;
if (!pNewElem)
{
return 0;
}
pNewElem->dwConnectionID = (XTP_CONNECTION_ID)pNewElem;
pNewElem->dwNotifyCode = Event;
pNewElem->pSink = pSink;
m_arrConnections.Add(pNewElem);
return pNewElem->dwConnectionID;
}
void CXTPNotifyConnection::Unadvise(XTP_CONNECTION_ID ConnectionID)
{
CSingleLock singleLock(GetDataLock(), TRUE);
try
{
int nCount = (int)m_arrConnections.GetSize();
int nFIndex = FindConnection(ConnectionID);
if (nFIndex >= 0 && nFIndex < nCount)
{
CONNECTION_DESCRIPTOR* pElem = m_arrConnections[nFIndex];
ASSERT(pElem);
if (pElem)
{
delete pElem;
}
m_arrConnections.RemoveAt(nFIndex);
}
else
{
ASSERT(FALSE);
}
}
catch(...)
{
ASSERT(FALSE);
TRACE(_T("EXCEPTION! CXTPNotifyConnection::Unadvise(ConnectionID = %d)\n"), ConnectionID);
}
}
BOOL CXTPNotifyConnection::SendEvent(XTP_NOTIFY_CODE Event,
WPARAM wParam , LPARAM lParam, DWORD dwFlags)
{
CSingleLock singleLock(GetDataLock(), TRUE);
InternalAddRef();
int nCount = (int)m_arrConnections.GetSize();
if (m_arrSendQueueCache.GetSize() < nCount + m_nSendQueueCacheSize)
{
m_arrSendQueueCache.SetSize(nCount + m_nSendQueueCacheSize);
}
//******************************************************************************
int nFirstLocalClientIndex = m_nSendQueueCacheSize;
int i;
for (i = 0; i < nCount; i++)
{
CONNECTION_DESCRIPTOR* pElem = m_arrConnections[i];
ASSERT(pElem);
if (pElem && pElem->dwNotifyCode == Event)
{
m_arrSendQueueCache.SetAt(m_nSendQueueCacheSize, *pElem);
m_nSendQueueCacheSize++;
}
}
int nLastLocalClientIndex = m_nSendQueueCacheSize-1;
singleLock.Unlock();
//************************************************************************
for (i = nFirstLocalClientIndex; i <= nLastLocalClientIndex; i++)
{
singleLock.Lock();
if (i >= m_arrSendQueueCache.GetSize())
{
ASSERT(FALSE);
return FALSE;
}
CONNECTION_DESCRIPTOR& rElem = m_arrSendQueueCache.ElementAt(i);
int nFIndex = FindConnection(rElem.dwConnectionID);
if (nFIndex < 0)
{
// Unadvise was called inside OnEvent(...) Call
continue;
}
try
{
CXTPNotifySink* ptrSink = rElem.pSink;
singleLock.Unlock();
if (ptrSink)
{
ptrSink->OnEvent(Event, wParam, lParam, dwFlags);
}
else
{
ASSERT(FALSE);
TRACE(_T("CXTPNotifyConnection::SendEvent(Event = %d, wParam = %d, lParam = %d, dwFlags = %x) pSink = %x\n"),
Event, wParam, lParam, dwFlags, rElem.pSink);
}
}
catch(...)
{
ASSERT(FALSE);
TRACE(_T("EXCEPTION! CXTPNotifyConnection::SendEvent(Event = %d, wParam = %d, lParam = %d, dwFlags = %x)\n"),
Event, wParam, lParam, dwFlags);
}
}
//==============================================================================
singleLock.Lock();
m_nSendQueueCacheSize = nFirstLocalClientIndex;
singleLock.Unlock();
InternalRelease();
return (nFirstLocalClientIndex <= nLastLocalClientIndex);
}
int CXTPNotifyConnection::FindConnection(XTP_CONNECTION_ID ConnectionID)
{
CSingleLock singleLock(GetDataLock(), TRUE);
int nCount = (int)m_arrConnections.GetSize();
for (int i = 0; i < nCount; i++)
{
CONNECTION_DESCRIPTOR* pCurElem = m_arrConnections[i];
ASSERT(pCurElem);
if (pCurElem)
{
if (pCurElem->dwConnectionID == ConnectionID)
{
return i;
}
}
}
return -1;
}
////////////////////////////////////////////////////////////////////////////
//class CXTPNotifyConnectionMT : public CXTPNotifyConnection
CXTPNotifyConnectionMT::CXTPNotifyConnectionMT()
{
}
CXTPNotifyConnectionMT::~CXTPNotifyConnectionMT()
{
}
////////////////////////////////////////////////////////////////////////////
BEGIN_MESSAGE_MAP(CXTPNotifySinkImplMTMsgWnd, CWnd)
ON_REGISTERED_MESSAGE(xtp_wm_NotificationSinkMTOnEvent, OnInterThreadEvent)
END_MESSAGE_MAP()
CXTPNotifySinkImplMTMsgWnd::CXTPNotifySinkImplMTMsgWnd()
{
}
CXTPNotifySinkImplMTMsgWnd::~CXTPNotifySinkImplMTMsgWnd()
{
}
BOOL CXTPNotifySinkImplMTMsgWnd::CreateWnd()
{
LPCTSTR pcszSimpleWndClass = AfxRegisterWndClass(0);
CRect rcEmpty(0, 0, 0, 0);
BOOL bCreated = CreateEx(0, pcszSimpleWndClass,
XTP_NOTIFICATION_SINK_MT_MSGWND_NAME,
WS_POPUP, rcEmpty, NULL, 0);
ASSERT(bCreated);
return bCreated;
}
//////////////////////////////////////////////////////////////////////////
// CXTPNotifySink
CXTPNotifySink::CXTPNotifySink()
{
}
CXTPNotifySink::~CXTPNotifySink()
{
UnadviseAll();
}
XTP_CONNECTION_ID CXTPNotifySink::Advise(CXTPNotifyConnection* pConnection,
XTP_NOTIFY_CODE dwNotifyCode)
{
ASSERT(pConnection);
if (!pConnection)
{
return 0;
}
XTP_CONNECTION_ID dwConnectionID = pConnection->Advise(dwNotifyCode, this);
ASSERT(dwConnectionID);
if (dwConnectionID)
{
ADVISE_DESCRIPTOR advDataNew;
ASSERT(!m_mapAdviseData.Lookup(dwConnectionID, advDataNew));
advDataNew.dwConnectionID = dwConnectionID;
advDataNew.pConnection = pConnection;
advDataNew.dwNotifyCode = dwNotifyCode;
pConnection->InternalAddRef();
m_mapAdviseData.SetAt(dwConnectionID, advDataNew);
}
return dwConnectionID;
}
void CXTPNotifySink::UnadviseAll()
{
XTP_CONNECTION_ID ConnectionID = 0;
ADVISE_DESCRIPTOR advData;
POSITION pos = m_mapAdviseData.GetStartPosition();
while (pos)
{
m_mapAdviseData.GetNextAssoc(pos, ConnectionID, advData);
if (advData.pConnection)
{
advData.pConnection->Unadvise(advData.dwConnectionID);
advData.pConnection->InternalRelease();
}
}
m_mapAdviseData.RemoveAll();
}
void CXTPNotifySink::Unadvise(XTP_CONNECTION_ID ConnectionID)
{
ADVISE_DESCRIPTOR advData;
if (m_mapAdviseData.Lookup(ConnectionID, advData))
{
if (advData.pConnection)
{
advData.pConnection->Unadvise(advData.dwConnectionID);
advData.pConnection->InternalRelease();
}
m_mapAdviseData.RemoveKey(ConnectionID);
}
else
{
ASSERT(FALSE);
}
}