[SHELL32]

- Introduce a CComCreatorSingleton class and use it for CDesktopFolder. Multiple calls to SHGetDesktopFolder will now return the same instance, which provides a massive speedup in many shell operations.
CORE-9839

svn path=/trunk/; revision=68210
This commit is contained in:
Thomas Faber 2015-06-20 16:54:52 +00:00
parent 6bb0bec44f
commit cc47f60138
4 changed files with 60 additions and 2 deletions

View file

@ -287,6 +287,7 @@ CDesktopFolder::CDesktopFolder() :
CDesktopFolder::~CDesktopFolder()
{
ASSERT(_CreatorClass::IsTerminated());
}
HRESULT WINAPI CDesktopFolder::FinalConstruct()

View file

@ -34,7 +34,7 @@ class CDesktopFolder :
/* both paths are parsible from the desktop */
LPWSTR sPathTarget; /* complete path to target used for enumeration and ChangeNotify */
LPITEMIDLIST pidlRoot; /* absolute pidl */
virtual HRESULT WINAPI _GetDropTarget(LPCITEMIDLIST pidl, LPVOID *ppvOut);
public:
@ -79,7 +79,7 @@ class CDesktopFolder :
virtual HRESULT WINAPI CopyItems(IShellFolder *pSFFrom, UINT cidl, LPCITEMIDLIST *apidl, BOOL bCopy);
DECLARE_REGISTRY_RESOURCEID(IDR_SHELLDESKTOP)
DECLARE_NOT_AGGREGATABLE(CDesktopFolder)
DECLARE_SINGLETON_NOT_AGGREGATABLE(CDesktopFolder)
DECLARE_PROTECT_FINAL_CONSTRUCT()

View file

@ -149,6 +149,11 @@ HRESULT WINAPI SHCreateDefClassObject(
class CShell32Module : public CComModule
{
public:
void Term()
{
CComCreatorSingleton< ATL::CComObject< CDesktopFolder > >::Term();
CComModule::Term();
}
};

View file

@ -41,6 +41,58 @@ extern "C" {
} /* extern "C" */
#endif /* defined(__cplusplus) */
#ifdef __cplusplus
template <typename T>
class CComCreatorSingleton
{
private:
static IUnknown *s_pInstance;
static bool s_IsTerminated;
public:
static HRESULT WINAPI CreateInstance(void *pv, REFIID riid, LPVOID *ppv)
{
*ppv = NULL;
if (pv != NULL)
return CLASS_E_NOAGGREGATION;
if (!s_pInstance)
{
PVOID pObj;
HRESULT hr;
hr = ATL::CComCreator< T >::CreateInstance(NULL, IID_IUnknown, &pObj);
if (FAILED(hr))
return hr;
if (InterlockedCompareExchangePointer((PVOID *)&s_pInstance, pObj, NULL))
static_cast<IUnknown *>(pObj)->Release();
}
return s_pInstance->QueryInterface(riid, ppv);
}
static void Term()
{
ULONG ref;
ASSERT(!s_IsTerminated);
s_IsTerminated = true;
if (s_pInstance)
{
ref = s_pInstance->Release();
ASSERT(ref == 0);
s_pInstance = NULL;
}
}
static bool IsTerminated() { return s_IsTerminated; }
};
template <typename T>
IUnknown *CComCreatorSingleton<T>::s_pInstance = NULL;
template <typename T>
bool CComCreatorSingleton<T>::s_IsTerminated = false;
#define DECLARE_SINGLETON_NOT_AGGREGATABLE(x) \
public: \
typedef CComCreatorSingleton< ATL::CComObject<x> > _CreatorClass;
#endif
#ifdef __cplusplus
template <class Base>
class CComDebugObject : public Base