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 #ifndef _THREADMANAGER_HXX
24 #define _THREADMANAGER_HXX
25 
26 #include <ithreadlistenerowner.hxx>
27 #include <vcl/timer.hxx>
28 #include <osl/mutex.hxx>
29 #include <osl/interlck.h>
30 #include <rtl/ref.hxx>
31 
32 #include <deque>
33 #include <list>
34 #include <cppuhelper/weak.hxx>
35 #include "com/sun/star/util/XJobManager.hpp"
36 #include <observablethread.hxx>
37 #include <cancellablejob.hxx>
38 #include <threadlistener.hxx>
39 
40 #include <boost/shared_ptr.hpp>
41 #include <boost/weak_ptr.hpp>
42 
43 /** class to manage threads
44 
45     OD 2007-01-29 #i73788#
46     An instance of this class takes care of the starting of threads.
47     It assures that not more than <mnStartedSize> threads
48     are started.
49 
50     @author OD
51 */
52 class ThreadManager : public IThreadListenerOwner
53 {
54     public:
55 
56         explicit ThreadManager( ::com::sun::star::uno::Reference< ::com::sun::star::util::XJobManager >& rThreadJoiner );
57         ~ThreadManager();
58 
59         // --> IThreadListenerOwner
60         virtual boost::weak_ptr< IFinishedThreadListener > GetThreadListenerWeakRef();
61         virtual void NotifyAboutFinishedThread( const oslInterlockedCount nThreadID );
62         // <--
63 
64         /** initialization
65 
66             IMPORTANT NOTE: Needs to be called directly after construction
67 
68             @author OD
69         */
70         void Init();
71 
72         /** add thread to the thread manager and taking ownership for the thread
73 
74             @author OD
75 
76             @return unique ID for added thread
77         */
78         oslInterlockedCount AddThread(
79                             const ::rtl::Reference< ObservableThread >& rThread );
80 
81         void RemoveThread( const oslInterlockedCount nThreadID,
82                            const bool bThreadFinished = false );
83 
84         DECL_LINK( TryToStartNewThread, Timer* );
85 
86         /** suspend the starting of threads
87 
88             Suspending the starting of further threads is sensible during the
89             destruction of a Writer document.
90 
91             @author OD
92         */
SuspendStartingOfThreads()93         inline void SuspendStartingOfThreads()
94         {
95             osl::MutexGuard aGuard(maMutex);
96 
97             mbStartingOfThreadsSuspended = true;
98         }
99 
100         /** continues the starting of threads after it has been suspended
101 
102             @author OD
103         */
104         void ResumeStartingOfThreads();
105 
StartingOfThreadsSuspended()106         inline bool StartingOfThreadsSuspended()
107         {
108             osl::MutexGuard aGuard(maMutex);
109 
110             return mbStartingOfThreadsSuspended;
111         }
112 
113         struct tThreadData
114         {
115             oslInterlockedCount nThreadID;
116             ::rtl::Reference< ObservableThread > pThread;
117             com::sun::star::uno::Reference< com::sun::star::util::XCancellable > aJob;
118 
tThreadDataThreadManager::tThreadData119             tThreadData()
120                 : nThreadID( 0 ),
121                   pThread( 0 ),
122                   aJob()
123             {}
124         };
125 
126     private:
127 
128         static const std::deque< tThreadData >::size_type mnStartedSize;
129 
130         osl::Mutex maMutex;
131 
132         ::com::sun::star::uno::WeakReference< ::com::sun::star::util::XJobManager > mrThreadJoiner;
133 
134         boost::shared_ptr< ThreadListener > mpThreadListener;
135 
136         oslInterlockedCount mnThreadIDCounter;
137 
138         std::deque< tThreadData > maWaitingForStartThreads;
139         std::deque< tThreadData > maStartedThreads;
140 
141         Timer maStartNewThreadTimer;
142 
143         bool mbStartingOfThreadsSuspended;
144 
145         struct ThreadPred
146         {
147             oslInterlockedCount mnThreadID;
ThreadPredThreadManager::ThreadPred148             explicit ThreadPred( oslInterlockedCount nThreadID )
149                 : mnThreadID( nThreadID )
150             {}
151 
operator ()ThreadManager::ThreadPred152             bool operator() ( const tThreadData& rThreadData ) const
153             {
154                 return rThreadData.nThreadID == mnThreadID;
155             }
156         };
157 
158 
RetrieveNewThreadID()159         inline oslInterlockedCount RetrieveNewThreadID()
160         {
161             return osl_incrementInterlockedCount( &mnThreadIDCounter );
162         }
163 
164         bool StartWaitingThread();
165 
166         bool StartThread( const tThreadData& aThreadData );
167 };
168 #endif
169