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