include/systools/win32/wait_for_multiple_objects.hxx | 37 ++++++++++++++++++ sal/osl/w32/conditn.cxx | 39 ++++--------------- vcl/win/dtrans/MtaOleClipb.cxx | 29 +------------- 3 files changed, 49 insertions(+), 56 deletions(-)
New commits: commit 6b6f8ca3dd4aa145519f5961f822435607d0e1d1 Author: Mike Kaganski <mike.kagan...@collabora.com> AuthorDate: Fri Jan 10 16:19:10 2025 +0500 Commit: Mike Kaganski <mike.kagan...@collabora.com> CommitDate: Fri Jan 10 14:12:52 2025 +0100 Factor out and simplify COM-safe wait Before commit 1e2e51607a163021ef1fb1fb0d217266bd448173 (Try to use CoWaitForMultipleHandles magic to handle COM message loop, 2025-01-10) osl_waitCondition didn't adjust the timeout value in the COM message processing loop. The abovementioned commit started to use a function that pumps the message loop itself, but the code for manual pumping wasn't removed (it has (likely) became dead). This drops the dead code, and deduplicates the rest. Change-Id: I0f7bbf8220792fbe42178c2689a065b5f38645d6 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/180069 Tested-by: Jenkins Reviewed-by: Mike Kaganski <mike.kagan...@collabora.com> diff --git a/include/systools/win32/wait_for_multiple_objects.hxx b/include/systools/win32/wait_for_multiple_objects.hxx new file mode 100644 index 000000000000..bcffe7013d8b --- /dev/null +++ b/include/systools/win32/wait_for_multiple_objects.hxx @@ -0,0 +1,37 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#pragma once + +#include <sal/config.h> + +#include <prewin.h> +#include <objbase.h> +#include <postwin.h> + +namespace sal::systools +{ +/* Like WaitForMultipleObjects function, but makes sure to process COM messages during the wait, + * allowing other threads access to COM objects instantiated in this thread. + */ +DWORD WaitForMultipleObjects_COMDispatch(DWORD count, const HANDLE* handles, DWORD timeout) +{ + DWORD dwResult; + HRESULT hr = CoWaitForMultipleHandles(COWAIT_DISPATCH_CALLS, timeout, count, + const_cast<LPHANDLE>(handles), &dwResult); + if (hr == RPC_S_CALLPENDING) + return WAIT_TIMEOUT; + if (FAILED(hr)) + return WAIT_FAILED; + + return dwResult; +} +} // sal::systools + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/sal/osl/w32/conditn.cxx b/sal/osl/w32/conditn.cxx index 0ad233ed9bff..9063899533c3 100644 --- a/sal/osl/w32/conditn.cxx +++ b/sal/osl/w32/conditn.cxx @@ -22,6 +22,7 @@ #include <osl/conditn.h> #include <osl/diagnose.h> #include <osl/time.h> +#include <systools/win32/wait_for_multiple_objects.hxx> /* under WIN32, we use the void* oslCondition @@ -75,39 +76,17 @@ oslConditionResult SAL_CALL osl_waitCondition(oslCondition Condition, /* It's necessary to process SendMessage calls to the current thread to give other threads access to COM objects instantiated in this thread */ - - while ( true ) + switch (sal::systools::WaitForMultipleObjects_COMDispatch( + 1, reinterpret_cast<HANDLE*>(&Condition), timeout)) { - DWORD index; - /* Only wake up if a SendMessage / COM call to the threads message loop is detected */ - HRESULT hr = CoWaitForMultipleHandles(COWAIT_DISPATCH_CALLS, timeout, 1, - reinterpret_cast<HANDLE*>(&Condition), &index); - if (hr == RPC_S_CALLPENDING) - return osl_cond_result_timeout; - if (FAILED(hr)) - return osl_cond_result_error; - switch (index) - { - case WAIT_OBJECT_0 + 1: - { - MSG msg; - - /* We Must not dispatch the message. PM_NOREMOVE leaves the message queue untouched - but dispatches SendMessage calls automatically */ + case WAIT_OBJECT_0: + return osl_cond_result_ok; - PeekMessageW( &msg, nullptr, 0, 0, PM_NOREMOVE ); - } - break; - - case WAIT_OBJECT_0: - return osl_cond_result_ok; - - case WAIT_TIMEOUT: - return osl_cond_result_timeout; + case WAIT_TIMEOUT: + return osl_cond_result_timeout; - default: - return osl_cond_result_error; - } + default: + return osl_cond_result_error; } } diff --git a/vcl/win/dtrans/MtaOleClipb.cxx b/vcl/win/dtrans/MtaOleClipb.cxx index b671578f5b45..98c9d1ac578e 100644 --- a/vcl/win/dtrans/MtaOleClipb.cxx +++ b/vcl/win/dtrans/MtaOleClipb.cxx @@ -45,6 +45,7 @@ #include <systools/win32/comtools.hxx> #include <systools/win32/retry_if_failed.hxx> +#include <systools/win32/wait_for_multiple_objects.hxx> #include <comphelper/windowserrorstring.hxx> @@ -67,8 +68,6 @@ namespace /* private */ const bool INIT_NONSIGNALED = false; /* Similar to osl conditions, with two condition objects passed to the Wait function. - COM Proxy-Stub communication uses SendMessages for - synchronization purposes. */ class Win32Condition { @@ -81,37 +80,15 @@ namespace /* private */ // leave messages sent through bool wait(HANDLE hEvtAbort) { - HANDLE hWaitArray[2] = { m_hEvent, hEvtAbort }; - while (true) + const HANDLE hWaitArray[2] = { m_hEvent, hEvtAbort }; + switch (sal::systools::WaitForMultipleObjects_COMDispatch(2, hWaitArray, INFINITE)) { - DWORD dwResult; - HRESULT hr = CoWaitForMultipleHandles(COWAIT_DISPATCH_CALLS, INFINITE, 2, - hWaitArray, &dwResult); - if (FAILED(hr)) - return false; - - switch (dwResult) - { case WAIT_OBJECT_0: // wait successful return true; case WAIT_OBJECT_0 + 1: // wait aborted - return false; - - case WAIT_OBJECT_0 + 2: - { - /* PeekMessage processes all messages in the SendMessage - queue that's what we want, messages from the PostMessage - queue stay untouched */ - MSG msg; - PeekMessageW(&msg, nullptr, 0, 0, PM_NOREMOVE); - - break; - } - default: // WAIT_FAILED? return false; - } } }