Jacek Caban : windowscodecs: Cache component info objects.

Alexandre Julliard julliard at winehq.org
Fri Mar 30 12:32:37 CDT 2018


Module: wine
Branch: master
Commit: 8a763d9e2952d2d58078c37bf722b033c9d4109f
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=8a763d9e2952d2d58078c37bf722b033c9d4109f

Author: Jacek Caban <jacek at codeweavers.com>
Date:   Thu Mar 29 20:50:35 2018 +0200

windowscodecs: Cache component info objects.

Signed-off-by: Jacek Caban <jacek at codeweavers.com>
Signed-off-by: Vincent Povirk <vincent at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/windowscodecs/info.c              | 47 +++++++++++++++++++++++++++++++++-
 dlls/windowscodecs/main.c              |  3 +++
 dlls/windowscodecs/tests/info.c        | 31 +++++++++++++++++++---
 dlls/windowscodecs/wincodecs_private.h |  1 +
 4 files changed, 78 insertions(+), 4 deletions(-)

diff --git a/dlls/windowscodecs/info.c b/dlls/windowscodecs/info.c
index 6d3272e..6114eef 100644
--- a/dlls/windowscodecs/info.c
+++ b/dlls/windowscodecs/info.c
@@ -33,6 +33,7 @@
 #include "wine/debug.h"
 #include "wine/unicode.h"
 #include "wine/list.h"
+#include "wine/rbtree.h"
 
 WINE_DEFAULT_DEBUG_CHANNEL(wincodecs);
 
@@ -60,6 +61,7 @@ typedef struct {
     IWICComponentInfo IWICComponentInfo_iface;
     LONG ref;
     CLSID clsid;
+    struct wine_rb_entry entry;
 } ComponentInfo;
 
 static HRESULT ComponentInfo_GetStringValue(HKEY classkey, LPCWSTR value,
@@ -1923,8 +1925,26 @@ static const struct category categories[] = {
     {0}
 };
 
+static int ComponentInfo_Compare(const void *key, const struct wine_rb_entry *entry)
+{
+    ComponentInfo *info = WINE_RB_ENTRY_VALUE(entry, ComponentInfo, entry);
+    return memcmp(key, &info->clsid, sizeof(info->clsid));
+}
+
+static struct wine_rb_tree component_info_cache = { ComponentInfo_Compare };
+
+static CRITICAL_SECTION component_info_cache_cs;
+static CRITICAL_SECTION_DEBUG component_info_cache_cs_dbg =
+{
+    0, 0, &component_info_cache_cs,
+    { &component_info_cache_cs_dbg.ProcessLocksList, &component_info_cache_cs_dbg.ProcessLocksList },
+      0, 0, { (DWORD_PTR)(__FILE__ ": component_info_cache") }
+};
+static CRITICAL_SECTION component_info_cache_cs = { &component_info_cache_cs_dbg, -1, 0, 0, 0, 0 };
+
 HRESULT CreateComponentInfo(REFCLSID clsid, IWICComponentInfo **ppIInfo)
 {
+    struct wine_rb_entry *cache_entry;
     ComponentInfo *info;
     HKEY clsidkey;
     HKEY classkey;
@@ -1936,9 +1956,23 @@ HRESULT CreateComponentInfo(REFCLSID clsid, IWICComponentInfo **ppIInfo)
     BOOL found = FALSE;
     HRESULT hr;
 
+    EnterCriticalSection(&component_info_cache_cs);
+
+    cache_entry = wine_rb_get(&component_info_cache, clsid);
+    if(cache_entry)
+    {
+        info = WINE_RB_ENTRY_VALUE(cache_entry, ComponentInfo, entry);
+        IWICComponentInfo_AddRef(*ppIInfo = &info->IWICComponentInfo_iface);
+        LeaveCriticalSection(&component_info_cache_cs);
+        return S_OK;
+    }
+
     res = RegOpenKeyExW(HKEY_CLASSES_ROOT, clsid_keyname, 0, KEY_READ, &clsidkey);
     if (res != ERROR_SUCCESS)
+    {
+        LeaveCriticalSection(&component_info_cache_cs);
         return HRESULT_FROM_WIN32(res);
+    }
 
     for (category=categories; category->type; category++)
     {
@@ -1980,10 +2014,21 @@ HRESULT CreateComponentInfo(REFCLSID clsid, IWICComponentInfo **ppIInfo)
     RegCloseKey(clsidkey);
 
     if (SUCCEEDED(hr))
-        *ppIInfo = &info->IWICComponentInfo_iface;
+    {
+        wine_rb_put(&component_info_cache, clsid, &info->entry);
+        IWICComponentInfo_AddRef(*ppIInfo = &info->IWICComponentInfo_iface);
+    }
+    LeaveCriticalSection(&component_info_cache_cs);
     return hr;
 }
 
+void ReleaseComponentInfos(void)
+{
+    ComponentInfo *info, *next_info;
+    WINE_RB_FOR_EACH_ENTRY_DESTRUCTOR(info, next_info, &component_info_cache, ComponentInfo, entry)
+        IWICComponentInfo_Release(&info->IWICComponentInfo_iface);
+}
+
 typedef struct {
     IEnumUnknown IEnumUnknown_iface;
     LONG ref;
diff --git a/dlls/windowscodecs/main.c b/dlls/windowscodecs/main.c
index 3bed565..6f781b8 100644
--- a/dlls/windowscodecs/main.c
+++ b/dlls/windowscodecs/main.c
@@ -42,6 +42,9 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
         case DLL_PROCESS_ATTACH:
             DisableThreadLibraryCalls(hinstDLL);
             break;
+        case DLL_PROCESS_DETACH:
+            ReleaseComponentInfos();
+            break;
     }
 
     return WIC_DllMain(hinstDLL, fdwReason, lpvReserved);
diff --git a/dlls/windowscodecs/tests/info.c b/dlls/windowscodecs/tests/info.c
index 4a9c9c6..d00e9d8 100644
--- a/dlls/windowscodecs/tests/info.c
+++ b/dlls/windowscodecs/tests/info.c
@@ -139,7 +139,6 @@ static void test_decoder_info(void)
             decoder_info2 = NULL;
             hr = IWICBitmapDecoder_GetDecoderInfo(decoder, &decoder_info2);
             ok(hr == S_OK, "Failed to get decoder info, hr %#x.\n", hr);
-        todo_wine
             ok(decoder_info == decoder_info2, "Unexpected decoder info instance.\n");
 
             hr = IWICBitmapDecoderInfo_QueryInterface(decoder_info, &IID_IWICBitmapDecoder, (void **)&decoder2);
@@ -470,17 +469,38 @@ static void test_pixelformat_info(void)
     IWICComponentInfo_Release(info);
 }
 
+static DWORD WINAPI cache_across_threads_test(void *arg)
+{
+    IWICComponentInfo *info;
+    HRESULT hr;
+
+    CoInitialize(NULL);
+
+    hr = get_component_info(&CLSID_WICUnknownMetadataReader, &info);
+    ok(hr == S_OK, "CreateComponentInfo failed, hr=%x\n", hr);
+    ok(info == arg, "unexpected info pointer %p\n", info);
+    IWICComponentInfo_Release(info);
+
+    CoUninitialize();
+    return 0;
+}
+
 static void test_reader_info(void)
 {
     IWICImagingFactory *factory;
-    IWICComponentInfo *info;
+    IWICComponentInfo *info, *info2;
     IWICMetadataReaderInfo *reader_info;
     HRESULT hr;
     CLSID clsid;
     GUID container_formats[10];
-    UINT count, size;
+    UINT count, size, tid;
+    HANDLE thread;
     WICMetadataPattern *patterns;
 
+    hr = get_component_info(&CLSID_WICUnknownMetadataReader, &info2);
+    ok(hr == S_OK, "CreateComponentInfo failed, hr=%x\n", hr);
+    IWICComponentInfo_Release(info2);
+
     hr = CoCreateInstance(&CLSID_WICImagingFactory, NULL, CLSCTX_INPROC_SERVER,
         &IID_IWICImagingFactory, (void**)&factory);
     ok(hr == S_OK, "CoCreateInstance failed, hr=%x\n", hr);
@@ -488,6 +508,11 @@ static void test_reader_info(void)
 
     hr = IWICImagingFactory_CreateComponentInfo(factory, &CLSID_WICUnknownMetadataReader, &info);
     ok(hr == S_OK, "CreateComponentInfo failed, hr=%x\n", hr);
+    ok(info == info2, "info != info2\n");
+
+    thread = CreateThread(NULL, 0, cache_across_threads_test, info, 0, &tid);
+    WaitForSingleObject(thread, INFINITE);
+    CloseHandle(thread);
 
     hr = IWICComponentInfo_QueryInterface(info, &IID_IWICMetadataReaderInfo, (void**)&reader_info);
     ok(hr == S_OK, "QueryInterface failed, hr=%x\n", hr);
diff --git a/dlls/windowscodecs/wincodecs_private.h b/dlls/windowscodecs/wincodecs_private.h
index c2c5ce4..037bde2 100644
--- a/dlls/windowscodecs/wincodecs_private.h
+++ b/dlls/windowscodecs/wincodecs_private.h
@@ -124,6 +124,7 @@ extern HRESULT CreatePropertyBag2(const PROPBAG2 *options, UINT count,
                                   IPropertyBag2 **property) DECLSPEC_HIDDEN;
 
 extern HRESULT CreateComponentInfo(REFCLSID clsid, IWICComponentInfo **ppIInfo) DECLSPEC_HIDDEN;
+extern void ReleaseComponentInfos(void) DECLSPEC_HIDDEN;
 extern HRESULT CreateComponentEnumerator(DWORD componentTypes, DWORD options, IEnumUnknown **ppIEnumUnknown) DECLSPEC_HIDDEN;
 
 typedef struct BmpDecoder BmpDecoder;




More information about the wine-cvs mailing list