1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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>
29 static void lcl_sleep( ::osl::Condition
& aCondition
,
30 ::sal_Int32 nMilliSeconds
)
32 if (nMilliSeconds
< 1)
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() )
57 void Request::notify()
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( )
70 , m_rHandler (rHandler
)
75 AsyncRequests::~AsyncRequests()
79 osl::MutexGuard
aLock(m_aMutex
);
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.
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
;
99 void AsyncRequests::triggerJobExecution()
107 void AsyncRequests::triggerRequestProcessMessages (const RequestRef
& rRequest
)
111 osl::MutexGuard
aLock(m_aMutex
);
112 m_lRequests
.push(rRequest
);
116 rRequest
->waitProcessMessages();
119 void AsyncRequests::triggerRequestBlocked(const RequestRef
& rRequest
)
123 osl::MutexGuard
aLock(m_aMutex
);
124 m_lRequests
.push(rRequest
);
128 triggerJobExecution();
133 void AsyncRequests::triggerRequestNonBlocked(const RequestRef
& rRequest
)
137 osl::MutexGuard
aLock(m_aMutex
);
138 m_lRequests
.push(rRequest
);
142 triggerJobExecution();
145 void AsyncRequests::triggerRequestDirectly(const RequestRef
& rRequest
)
148 osl::ClearableMutexGuard
aLock(m_aMutex
);
149 RequestHandlerRef rHandler
= m_rHandler
;
153 if (rHandler
!= nullptr)
154 rHandler
->doRequest(rRequest
);
157 void AsyncRequests::triggerRequestThreadAware(const RequestRef
& rRequest
,
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
);
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;
180 ::osl::ResettableMutexGuard
aLock(m_aMutex
);
181 RequestHandlerRef rHandler
= m_rHandler
;
182 bool bFinished
= m_bFinish
;
186 if (rHandler
!= nullptr)
195 if ( ! m_lRequests
.empty())
197 rRequest
= m_lRequests
.front();
200 bFinished
= m_bFinish
;
205 if (rRequest
== nullptr)
207 lcl_sleep(maWait
, TIME_TO_WAIT_FOR_NEW_REQUESTS
);
212 if (rHandler
!= nullptr)
214 rHandler
->doRequest(rRequest
);
219 if (rHandler
!= nullptr)
225 } // namespace fpicker
227 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */