Author: tfaber Date: Sat Jun 20 16:54:52 2015 New Revision: 68210
URL: http://svn.reactos.org/svn/reactos?rev=68210&view=rev Log: [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
Modified: trunk/reactos/dll/win32/shell32/folders/CDesktopFolder.cpp trunk/reactos/dll/win32/shell32/folders/CDesktopFolder.h trunk/reactos/dll/win32/shell32/shell32.cpp trunk/reactos/include/reactos/shellutils.h
Modified: trunk/reactos/dll/win32/shell32/folders/CDesktopFolder.cpp URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/shell32/folders/C... ============================================================================== --- trunk/reactos/dll/win32/shell32/folders/CDesktopFolder.cpp [iso-8859-1] (original) +++ trunk/reactos/dll/win32/shell32/folders/CDesktopFolder.cpp [iso-8859-1] Sat Jun 20 16:54:52 2015 @@ -287,6 +287,7 @@
CDesktopFolder::~CDesktopFolder() { + ASSERT(_CreatorClass::IsTerminated()); }
HRESULT WINAPI CDesktopFolder::FinalConstruct()
Modified: trunk/reactos/dll/win32/shell32/folders/CDesktopFolder.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/shell32/folders/C... ============================================================================== --- trunk/reactos/dll/win32/shell32/folders/CDesktopFolder.h [iso-8859-1] (original) +++ trunk/reactos/dll/win32/shell32/folders/CDesktopFolder.h [iso-8859-1] Sat Jun 20 16:54:52 2015 @@ -34,7 +34,7 @@ /* 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 @@ 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()
Modified: trunk/reactos/dll/win32/shell32/shell32.cpp URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/shell32/shell32.c... ============================================================================== --- trunk/reactos/dll/win32/shell32/shell32.cpp [iso-8859-1] (original) +++ trunk/reactos/dll/win32/shell32/shell32.cpp [iso-8859-1] Sat Jun 20 16:54:52 2015 @@ -149,6 +149,11 @@ class CShell32Module : public CComModule { public: + void Term() + { + CComCreatorSingleton< ATL::CComObject< CDesktopFolder > >::Term(); + CComModule::Term(); + } };
Modified: trunk/reactos/include/reactos/shellutils.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/include/reactos/shellutils.... ============================================================================== --- trunk/reactos/include/reactos/shellutils.h [iso-8859-1] (original) +++ trunk/reactos/include/reactos/shellutils.h [iso-8859-1] Sat Jun 20 16:54:52 2015 @@ -40,6 +40,58 @@ #ifdef __cplusplus } /* 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>