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 #ifndef SD_SLIDESORTER_QUEUE_PROCESSOR_THREAD_HXX
25 #define SD_SLIDESORTER_QUEUE_PROCESSOR_THREAD_HXX
26
27 #include "view/SlsPageObjectViewObjectContact.hxx"
28 #include <vcl/svapp.hxx>
29 #include <osl/thread.hxx>
30
31 namespace sd { namespace slidesorter { namespace view {
32 class SlideSorterView;
33 } } }
34
35
36 namespace sd { namespace slidesorter { namespace cache {
37
38
39 template <class Queue,
40 class RequestData,
41 class BitmapCache,
42 class BitmapFactory>
43 class QueueProcessorThread
44 : public ::osl::Thread
45 {
46 public:
47 QueueProcessorThread (
48 view::SlideSorterView& rView,
49 Queue& rQueue,
50 BitmapCache& rCache);
51 ~QueueProcessorThread (void);
52
53 /** Start the execution of a suspended thread. A thread is suspended
54 after Stop() is called or when the queue on which it operates is
55 empty. Calling Start() on a running thread is OK.
56 */
57 void Start (void);
58
59 /** Stop the thread by suspending it. To re-start its execution call
60 Start().
61 */
62 void Stop (void);
63
64 /** As we can not really terminate the rendering of a preview bitmap for
65 a request in midair this method acts more like a semaphor. It
66 returns only when it is save for the caller to delete the request.
67 For this to work it is important to remove the request from the
68 queue before calling this method.
69 */
70 void RemoveRequest (RequestData& rRequest);
71
72 /** Terminate the execution of the thread. When the thread is detached
73 it deletes itself. Otherwise the caller of this method may call
74 delete after this method returnes.
75 */
76 void SAL_CALL Terminate (void);
77
78 protected:
79 /** This virtual method is called (among others?) from the
80 inherited create method and acts as the main function of this
81 thread.
82 */
83 virtual void SAL_CALL run (void);
84
85 /** Called after the thread is terminated via the terminate
86 method. Used to kill the thread by calling delete on this.
87 */
88 virtual void SAL_CALL onTerminated (void);
89
90 private:
91 /** Flag that indicates whether the onTerminated method has been already
92 called. If so then a subsequent call to detach deletes the thread.
93 */
94 volatile bool mbIsTerminated;
95
96 volatile bool mbCanBeJoined;
97
98 /** This mutex is used to guard the queue processor. Be careful not to
99 mix its use with that of the solar mutex.
100 */
101 ::osl::Mutex maMutex;
102
103 view::SlideSorterView& mrView;
104 Queue& mrQueue;
105 BitmapCache& mrCache;
106
107 void ProcessQueueEntry (void);
108 };
109
110
111
112
113 //===== QueueProcessorThread ================================================
114
115 template <class Queue, class Request, class Cache, class Factory>
116 QueueProcessorThread<Queue, Request, Cache, Factory>
QueueProcessorThread(view::SlideSorterView & rView,Queue & rQueue,Cache & rCache)117 ::QueueProcessorThread (
118 view::SlideSorterView& rView,
119 Queue& rQueue,
120 Cache& rCache)
121 : mbIsTerminated (false),
122 mbCanBeJoined (false),
123 mrView (rView),
124 mrQueue (rQueue),
125 mrCache (rCache)
126 {
127 create();
128 }
129
130
131
132
133 template <class Queue, class Request, class Cache, class Factory>
134 QueueProcessorThread<Queue, Request, Cache, Factory>
~QueueProcessorThread(void)135 ::~QueueProcessorThread (void)
136 {
137 }
138
139
140
141
142 template <class Queue, class Request, class Cache, class Factory>
run(void)143 void SAL_CALL QueueProcessorThread<Queue, Request, Cache, Factory>::run (void)
144 {
145 while ( ! mbIsTerminated)
146 {
147 if (mrQueue.IsEmpty())
148 {
149 // Sleep while the queue is empty.
150 suspend();
151 }
152
153 else if (GetpApp()->AnyInput())
154 {
155 yield();
156 // When there is input waiting to be processed we wait a short
157 // time and try again.
158 TimeValue aTimeToWait;
159 aTimeToWait.Seconds = 0;
160 aTimeToWait.Nanosec = 50*1000*1000;
161 wait (aTimeToWait);
162 }
163
164 else
165 {
166 ProcessQueueEntry();
167 yield ();
168 }
169 }
170 }
171
172
173
174
175 template <class Queue, class Request, class Cache, class Factory>
176 void QueueProcessorThread<Queue, Request, Cache, Factory>
ProcessQueueEntry(void)177 ::ProcessQueueEntry (void)
178 {
179 Request* pRequest = NULL;
180 int nPriorityClass;
181 bool bRequestIsValid = false;
182
183 do
184 {
185 {
186 ::osl::MutexGuard aGuard (maMutex);
187 if (mbIsTerminated)
188 break;
189 if (mrQueue.IsEmpty())
190 break;
191 }
192 ::vos::OGuard aSolarGuard (Application::GetSolarMutex());
193 ::osl::MutexGuard aGuard (maMutex);
194 if (mbIsTerminated)
195 break;
196
197 if (mrQueue.IsEmpty())
198 break;
199
200 // Get the requeuest with the highest priority from the queue.
201 nPriorityClass = mrQueue.GetFrontPriorityClass();
202 pRequest = &mrQueue.GetFront();
203 mrQueue.PopFront();
204 bRequestIsValid = true;
205
206 try
207 {
208 // Create a new preview bitmap and store it in the cache.
209 if (mbIsTerminated)
210 break;
211 BitmapEx aBitmap (Factory::CreateBitmap (*pRequest, mrView));
212 if (mbIsTerminated)
213 break;
214 mrCache.SetBitmap (
215 pRequest->GetPage(),
216 aBitmap,
217 nPriorityClass==0);
218 }
219 catch (...)
220 {
221 OSL_TRACE ("QueueProcessorThread::ProcessQueueEntry(): caught exception; %p", this);
222 // We are rendering a preview and can do without if need
223 // be. So keep going if something happens that should
224 // not happen.
225 }
226 }
227 while (false);
228 }
229
230
231
232
233 template <class Queue,
234 class RequestData,
235 class BitmapCache,
236 class BitmapFactory>
237 void QueueProcessorThread<
238 Queue, RequestData, BitmapCache, BitmapFactory
Start(void)239 >::Start (void)
240 {
241 resume ();
242 }
243
244
245
246
247 template <class Queue,
248 class RequestData,
249 class BitmapCache,
250 class BitmapFactory>
251 void QueueProcessorThread<
252 Queue, RequestData, BitmapCache, BitmapFactory
Stop(void)253 >::Stop (void)
254 {
255 suspend();
256 }
257
258
259
260
261 template <class Queue,
262 class RequestData,
263 class BitmapCache,
264 class BitmapFactory>
265 void QueueProcessorThread<
266 Queue, RequestData, BitmapCache, BitmapFactory
RemoveRequest(RequestData & rRequest)267 >::RemoveRequest (RequestData& rRequest)
268 {
269 // Do nothing else then wait for the mutex to be released.
270 ::osl::MutexGuard aGuard (mrQueue.GetMutex());
271 }
272
273
274
275
276 template <class Queue,
277 class RequestData,
278 class BitmapCache,
279 class BitmapFactory>
280 void QueueProcessorThread<
281 Queue, RequestData, BitmapCache, BitmapFactory
Terminate(void)282 >::Terminate (void)
283 {
284 // ::vos::OGuard aSolarGuard (Application::GetSolarMutex());
285 ::osl::Thread::terminate ();
286 {
287 ::osl::MutexGuard aGuard (maMutex);
288 mbIsTerminated = true;
289 }
290 Start();
291 }
292
293
294
295
296 /** This callback method is called when the run() method terminates.
297 */
298 template <class Queue,
299 class RequestData,
300 class BitmapCache,
301 class BitmapFactory>
302 void SAL_CALL QueueProcessorThread<
303 Queue, RequestData, BitmapCache, BitmapFactory
onTerminated(void)304 >::onTerminated (void)
305 {
306 ::osl::MutexGuard aGuard (maMutex);
307 mbCanBeJoined = true;
308 }
309
310
311
312
313 } } } // end of namespace ::sd::slidesorter::cache
314
315 #endif
316