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/CDesktopFolder.cpp?rev=68210&r1=68209&r2=68210&view=diff
==============================================================================
--- 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/CDesktopFolder.h?rev=68210&r1=68209&r2=68210&view=diff
==============================================================================
--- 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.cpp?rev=68210&r1=68209&r2=68210&view=diff
==============================================================================
--- 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.h?rev=68210&r1=68209&r2=68210&view=diff
==============================================================================
--- 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>


Reply via email to