1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 #include "asyncrequests.hxx"
25 #include <vcl/svapp.hxx>
26 #include <vos/mutex.hxx>
27 
28 //-----------------------------------------------------------------------------
29 // namespace
30 //-----------------------------------------------------------------------------
31 
32 namespace fpicker{
33 namespace win32{
34 namespace vista{
35 
36 namespace css = ::com::sun::star;
37 
38 //-----------------------------------------------------------------------------
lcl_sleep(::osl::Condition & aCondition,::sal_Int32 nMilliSeconds)39 void lcl_sleep(::osl::Condition& aCondition   ,
40                ::sal_Int32       nMilliSeconds)
41 {
42 	sal_uLong nAcquireCount = Application::ReleaseSolarMutex();
43 
44     if (nMilliSeconds < 1)
45         aCondition.wait(0);
46     else
47     {
48         TimeValue aTime;
49         aTime.Seconds = (nMilliSeconds / 1000);
50         aTime.Nanosec = (nMilliSeconds % 1000) * 1000000;
51         aCondition.wait(&aTime);
52     }
53 
54 	Application::AcquireSolarMutex( nAcquireCount );
55 }
56 
57 //-----------------------------------------------------------------------------
wait(::sal_Int32 nMilliSeconds)58 void Request::wait(::sal_Int32 nMilliSeconds)
59 {
60     lcl_sleep(m_aJoiner, nMilliSeconds);
61 }
62 
waitProcessMessages()63 void Request::waitProcessMessages()
64 {
65 	::vos::OGuard aGuard( Application::GetSolarMutex() );
66 	while (!m_aJoiner.check())
67 		Application::Yield();
68 }
69 
70 //-----------------------------------------------------------------------------
notify()71 void Request::notify()
72 {
73     m_aJoiner.set();
74 }
75 
76 //-----------------------------------------------------------------------------
AsyncRequests(const RequestHandlerRef & rHandler)77 AsyncRequests::AsyncRequests(const RequestHandlerRef& rHandler)
78     : ::cppu::BaseMutex(         )
79     , ::osl::Thread    (         )
80     , m_bFinish        (sal_False)
81     , m_rHandler       (rHandler )
82     , m_lRequests      (         )
83 {
84 }
85 
86 //-----------------------------------------------------------------------------
~AsyncRequests()87 AsyncRequests::~AsyncRequests()
88 {
89     // SYNCHRONIZED ->
90     ::osl::ResettableMutexGuard aLock(m_aMutex);
91     m_bFinish = sal_True;
92     aLock.clear();
93     // <- SYNCHRONIZED
94 
95     join();
96 }
97 
triggerRequestProcessMessages(const RequestRef & rRequest)98 void AsyncRequests::triggerRequestProcessMessages (const RequestRef& rRequest)
99 {
100 	// SYNCHRONIZED ->
101     ::osl::ResettableMutexGuard aLock(m_aMutex);
102     m_lRequests.push(rRequest);
103     aLock.clear();
104     // <- SYNCHRONIZED
105 
106     if ( ! isRunning())
107         create();
108 
109 	rRequest->waitProcessMessages();
110 }
111 
112 //-----------------------------------------------------------------------------
triggerRequestBlocked(const RequestRef & rRequest)113 void AsyncRequests::triggerRequestBlocked(const RequestRef& rRequest)
114 {
115     // SYNCHRONIZED ->
116     ::osl::ResettableMutexGuard aLock(m_aMutex);
117     m_lRequests.push(rRequest);
118     aLock.clear();
119     // <- SYNCHRONIZED
120 
121     if ( ! isRunning())
122         create();
123 
124     rRequest->wait(Request::WAIT_INFINITE);
125 }
126 
127 //-----------------------------------------------------------------------------
triggerRequestNonBlocked(const RequestRef & rRequest)128 void AsyncRequests::triggerRequestNonBlocked(const RequestRef& rRequest)
129 {
130     // SYNCHRONIZED ->
131     ::osl::ResettableMutexGuard aLock(m_aMutex);
132     m_lRequests.push(rRequest);
133     aLock.clear();
134     // <- SYNCHRONIZED
135 
136     if ( ! isRunning())
137         create();
138 }
139 
140 //-----------------------------------------------------------------------------
triggerRequestDirectly(const RequestRef & rRequest)141 void AsyncRequests::triggerRequestDirectly(const RequestRef& rRequest)
142 {
143     // SYNCHRONIZED ->
144     ::osl::ResettableMutexGuard aLock(m_aMutex);
145     RequestHandlerRef rHandler = m_rHandler;
146     aLock.clear();
147     // <- SYNCHRONIZED
148 
149     if (rHandler != NULL)
150         rHandler->doRequest(rRequest);
151 }
152 
153 //-----------------------------------------------------------------------------
triggerRequestThreadAware(const RequestRef & rRequest,::sal_Int16 nWait)154 void AsyncRequests::triggerRequestThreadAware(const RequestRef& rRequest,
155                                                     ::sal_Int16  nWait   )
156 {
157     oslThreadIdentifier nOurThreadId    = getIdentifier();
158     oslThreadIdentifier nCallerThreadId = ::osl::Thread::getCurrentIdentifier();
159     if (nOurThreadId == nCallerThreadId)
160         triggerRequestDirectly(rRequest);
161     else if (nWait == BLOCKED)
162         triggerRequestBlocked(rRequest);
163     else if (nWait == PROCESS_MESSAGES)
164 		triggerRequestProcessMessages(rRequest);
165 	else
166         triggerRequestNonBlocked(rRequest);
167 }
168 
169 //-----------------------------------------------------------------------------
170 
171 
172 //-----------------------------------------------------------------------------
run()173 void SAL_CALL AsyncRequests::run()
174 {
175     static const ::sal_Int32 TIME_TO_WAIT_FOR_NEW_REQUESTS = 250;
176 
177     // SYNCHRONIZED ->
178     ::osl::ResettableMutexGuard aLock(m_aMutex);
179     RequestHandlerRef rHandler  = m_rHandler;
180     ::sal_Bool        bFinished = m_bFinish;
181     aLock.clear();
182     // <- SYNCHRONIZED
183 
184     if (rHandler != NULL)
185         rHandler->before();
186 
187     ::osl::Condition aWait;
188 
189     while ( ! bFinished)
190     {
191         // SYNCHRONIZED ->
192         aLock.reset();
193 
194         RequestRef rRequest;
195         if ( ! m_lRequests.empty())
196         {
197             rRequest = m_lRequests.front();
198                        m_lRequests.pop();
199         }
200         bFinished = m_bFinish;
201 
202         aLock.clear();
203         // <- SYNCHRONIZED
204 
205         if (rRequest == NULL)
206         {
207             lcl_sleep(aWait, TIME_TO_WAIT_FOR_NEW_REQUESTS);
208             continue;
209         }
210 
211         if (rHandler != NULL)
212         {
213             rHandler->doRequest(rRequest);
214             rRequest->notify();
215         }
216     }
217 
218     if (rHandler != NULL)
219         rHandler->after();
220 }
221 
222 } // namespace vista
223 } // namespace win32
224 } // namespace fpicker
225