/** * @file XTPSingleton.cpp * * @copyright * (c) 1998-2025 Codejock Software, All Rights Reserved. * * This source file is the property of Codejock Software and must not be * redistributed by any means without the explicit written permission of * Codejock Software. * * The use of this source code is governed by the terms and conditions specified * in the Toolkit Pro license agreement. Codejock Software grants you, as a * single software developer, the limited right to use this software on one * computer only. * * Contact Information: * support@codejock.com * http://www.codejock.com * */ #include "stdafx.h" #include "Common/XTPTypeId.h" #include "Common/XTPSynchro.h" #include "Common/XTPSystemHelpers.h" #include "Common/XTPApplication.h" #include "Common/XTPSingleton.h" #include "Common/Base/Diagnostic/XTPDisableNoisyWarnings.h" #ifdef _DEBUG # define new DEBUG_NEW # undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif CXTPSingletonPointer::CXTPSingletonPointer(SIZE_T cbObjectSize, Creator pfnCreator, Destroyer pfnDestroyer, Initializer pfnInitializer /*= NULL*/) : m_pInstance(NULL) , m_cbObjectSize(cbObjectSize) , m_pfnCreator(pfnCreator) , m_pfnDestroyer(pfnDestroyer) , m_bDestroyed(FALSE) { _ASSERTE(1 <= m_cbObjectSize); _ASSERTE(NULL != m_pfnCreator); _ASSERTE(NULL != m_pfnDestroyer); if (NULL != pfnInitializer) { pfnInitializer(); } ::InitializeCriticalSection(&m_access); XTPAccessExclusive(XTPGetApplication())->Subscribe(this); } CXTPSingletonPointer::~CXTPSingletonPointer() { Destroy(); ::DeleteCriticalSection(&m_access); } void* CXTPSingletonPointer::GetInstance() { _ASSERTE(!m_bDestroyed); if (m_bDestroyed) { AfxThrowMemoryException(); } if (NULL == m_pInstance) { ::EnterCriticalSection(&m_access); if (NULL == m_pInstance) { XTP_GUARD_EXCLUSIVE_(CXTPApplication, XTPGetApplication(), pApp) { BOOL bAppReady = pApp->IsReady(); _ASSERTE("The main application object has not been initialized yet or has been " "destroyed already. A common cause of this condition is that the main " "application class is not derived from CXTPWinApp or XTPInitialize has " "not been called instead. Refer to CXTPWinApp and XTPInitialize " "documentation for more details. The application will abort now." && bAppReady); if (!bAppReady) abort(); // It is necessary to use low level API at this point // as runtime might not be initialized properly for 'new' or 'malloc'. m_pInstance = ::HeapAlloc(::GetProcessHeap(), HEAP_ZERO_MEMORY, m_cbObjectSize); if (NULL != m_pInstance) { if (!m_pfnCreator(m_pInstance)) { ::HeapFree(::GetProcessHeap(), 0, m_pInstance); m_pInstance = NULL; } } } } ::LeaveCriticalSection(&m_access); if (NULL == m_pInstance) { AfxThrowMemoryException(); } } return m_pInstance; } void CXTPSingletonPointer::Destroy() { if (!m_bDestroyed) { XTPAccessExclusive(XTPGetApplication())->Unsubscribe(this); if (NULL != m_pInstance) { m_pfnDestroyer(m_pInstance); // It is necessary to use low level API at this point // as runtime might not be initialized properly for 'delete' or 'free'. ::HeapFree(::GetProcessHeap(), 0, m_pInstance); m_pInstance = NULL; } m_bDestroyed = TRUE; } } void CXTPSingletonPointer::OnApplicationShutdown(CXTPApplication* pApplication) { UNREFERENCED_PARAMETER(pApplication); Destroy(); }