Version 6.4.0.0.beta1, tag libreoffice-6.4.0.0.beta1
[LibreOffice.git] / fpicker / source / win32 / asyncrequests.cxx
blob86b71cf5154097c7baf23de9570c58ac7c4f3392
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include "asyncrequests.hxx"
21 #include <vcl/svapp.hxx>
22 #include <vcl/winscheduler.hxx>
23 #include <osl/mutex.hxx>
25 namespace fpicker{
26 namespace win32{
27 namespace vista{
29 static void lcl_sleep( ::osl::Condition& aCondition,
30 ::sal_Int32 nMilliSeconds )
32 if (nMilliSeconds < 1)
33 aCondition.wait();
34 else
36 TimeValue aTime;
37 aTime.Seconds = (nMilliSeconds / 1000);
38 aTime.Nanosec = (nMilliSeconds % 1000) * 1000000;
39 aCondition.wait(&aTime);
43 void Request::wait( ::sal_Int32 nMilliSeconds )
45 SolarMutexReleaser aReleaser;
47 lcl_sleep( m_aJoiner, nMilliSeconds );
50 void Request::waitProcessMessages()
52 SolarMutexGuard aGuard;
53 while ( !m_aJoiner.check() )
54 Application::Yield();
57 void Request::notify()
59 m_aJoiner.set();
60 // Make sure that main loop receives at least this message to return from GetMessage and recheck
61 // the condition, even in case when there's no visible application windows present, and thus no
62 // other messages might arrive to the main loop.
63 WinScheduler::PostDummyMessage();
66 AsyncRequests::AsyncRequests(const RequestHandlerRef& rHandler)
67 : ::cppu::BaseMutex( )
68 , ::osl::Thread ( )
69 , m_bFinish (false)
70 , m_rHandler (rHandler )
71 , m_lRequests ( )
75 AsyncRequests::~AsyncRequests()
77 // SYNCHRONIZED ->
79 osl::MutexGuard aLock(m_aMutex);
80 m_bFinish = true;
82 // <- SYNCHRONIZED
84 // The static AsyncRequests aNotify in VistaFilePickerEventHandler::impl_sendEvent
85 // is destructed at DLL atexit. But it won't run, so needs no join and release of
86 // the already destructed SolarMutex, which would crash LO on exit.
87 if (isRunning())
89 // tdf#123502: make sure we actually hold the mutex before releasing it
90 // UNO directly destroys the VistaFilePicker object, so we need GUI protection in there.
91 // But since we redirect GUI stuff to the async thread we also have to release it, so we
92 // can join it, if the thread currently blocks on the SolarMutex.
93 SolarMutexGuard aGuard;
94 SolarMutexReleaser aReleaser;
95 join();
99 void AsyncRequests::triggerJobExecution()
101 if ( ! isRunning())
102 create();
103 else
104 maWait.set();
107 void AsyncRequests::triggerRequestProcessMessages (const RequestRef& rRequest)
109 // SYNCHRONIZED ->
111 osl::MutexGuard aLock(m_aMutex);
112 m_lRequests.push(rRequest);
114 // <- SYNCHRONIZED
116 rRequest->waitProcessMessages();
119 void AsyncRequests::triggerRequestBlocked(const RequestRef& rRequest)
121 // SYNCHRONIZED ->
123 osl::MutexGuard aLock(m_aMutex);
124 m_lRequests.push(rRequest);
126 // <- SYNCHRONIZED
128 triggerJobExecution();
130 rRequest->wait();
133 void AsyncRequests::triggerRequestNonBlocked(const RequestRef& rRequest)
135 // SYNCHRONIZED ->
137 osl::MutexGuard aLock(m_aMutex);
138 m_lRequests.push(rRequest);
140 // <- SYNCHRONIZED
142 triggerJobExecution();
145 void AsyncRequests::triggerRequestDirectly(const RequestRef& rRequest)
147 // SYNCHRONIZED ->
148 osl::ClearableMutexGuard aLock(m_aMutex);
149 RequestHandlerRef rHandler = m_rHandler;
150 aLock.clear();
151 // <- SYNCHRONIZED
153 if (rHandler != nullptr)
154 rHandler->doRequest(rRequest);
157 void AsyncRequests::triggerRequestThreadAware(const RequestRef& rRequest,
158 ::sal_Int16 nWait )
160 oslThreadIdentifier nOurThreadId = getIdentifier();
161 oslThreadIdentifier nCallerThreadId = ::osl::Thread::getCurrentIdentifier();
162 SolarMutexGuard aGuard;
163 if (nOurThreadId == nCallerThreadId)
164 triggerRequestDirectly(rRequest);
165 else if (nWait == BLOCKED)
166 triggerRequestBlocked(rRequest);
167 else if (nWait == PROCESS_MESSAGES)
168 triggerRequestProcessMessages(rRequest);
169 else
170 triggerRequestNonBlocked(rRequest);
173 void SAL_CALL AsyncRequests::run()
175 osl_setThreadName("fpicker::win32::vista::AsyncRequests");
177 static const ::sal_Int32 TIME_TO_WAIT_FOR_NEW_REQUESTS = 250;
179 // SYNCHRONIZED ->
180 ::osl::ResettableMutexGuard aLock(m_aMutex);
181 RequestHandlerRef rHandler = m_rHandler;
182 bool bFinished = m_bFinish;
183 aLock.clear();
184 // <- SYNCHRONIZED
186 if (rHandler != nullptr)
187 rHandler->before();
189 while ( ! bFinished)
191 // SYNCHRONIZED ->
192 aLock.reset();
194 RequestRef rRequest;
195 if ( ! m_lRequests.empty())
197 rRequest = m_lRequests.front();
198 m_lRequests.pop();
200 bFinished = m_bFinish;
202 aLock.clear();
203 // <- SYNCHRONIZED
205 if (rRequest == nullptr)
207 lcl_sleep(maWait, TIME_TO_WAIT_FOR_NEW_REQUESTS);
208 maWait.reset();
209 continue;
212 if (rHandler != nullptr)
214 rHandler->doRequest(rRequest);
215 rRequest->notify();
219 if (rHandler != nullptr)
220 rHandler->after();
223 } // namespace vista
224 } // namespace win32
225 } // namespace fpicker
227 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */