xref: /AOO41X/main/cppu/source/threadpool/jobqueue.cxx (revision 129fa3d1fc5edc85a690d91de1660cefa4e8a95b)
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 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_cppu.hxx"
26 #include "jobqueue.hxx"
27 #include "threadpool.hxx"
28 
29 #include <osl/diagnose.h>
30 
31 using namespace ::osl;
32 
33 namespace cppu_threadpool {
34 
JobQueue()35     JobQueue::JobQueue() :
36         m_nToDo( 0 ),
37         m_bSuspended( sal_False ),
38         m_cndWait( osl_createCondition() )
39     {
40         osl_resetCondition( m_cndWait );
41         m_DisposedCallerAdmin = DisposedCallerAdmin::getInstance();
42     }
43 
~JobQueue()44     JobQueue::~JobQueue()
45     {
46         osl_destroyCondition( m_cndWait );
47     }
48 
49 
add(void * pThreadSpecificData,RequestFun * doRequest)50     void JobQueue::add( void *pThreadSpecificData, RequestFun * doRequest )
51     {
52         MutexGuard guard( m_mutex );
53         Job job = { pThreadSpecificData , doRequest };
54         m_lstJob.push_back( job );
55         if( ! m_bSuspended )
56         {
57             osl_setCondition( m_cndWait );
58         }
59         m_nToDo ++;
60     }
61 
enter(sal_Int64 nDisposeId,sal_Bool bReturnWhenNoJob)62     void *JobQueue::enter( sal_Int64 nDisposeId , sal_Bool bReturnWhenNoJob )
63     {
64         void *pReturn = 0;
65         {
66             // synchronize with the dispose calls
67             MutexGuard guard( m_mutex );
68             if( m_DisposedCallerAdmin->isDisposed( nDisposeId ) )
69             {
70                 return 0;
71             }
72             m_lstCallstack.push_front( nDisposeId );
73         }
74 
75 
76         while( sal_True )
77         {
78             if( bReturnWhenNoJob )
79             {
80                 MutexGuard guard( m_mutex );
81                 if( m_lstJob.empty() )
82                 {
83                     break;
84                 }
85             }
86 
87             osl_waitCondition( m_cndWait , 0 );
88 
89             struct Job job={0,0};
90             {
91                 // synchronize with add and dispose calls
92                 MutexGuard guard( m_mutex );
93 
94                 if( 0 == m_lstCallstack.front() )
95                 {
96                     // disposed !
97                     if( m_lstJob.empty() )
98                     {
99                         osl_resetCondition( m_cndWait );
100                     }
101                     break;
102                 }
103 
104                 OSL_ASSERT( ! m_lstJob.empty() );
105                 if( ! m_lstJob.empty() )
106                 {
107                     job = m_lstJob.front();
108                     m_lstJob.pop_front();
109                 }
110                 if( m_lstJob.empty() )
111                 {
112                     osl_resetCondition( m_cndWait );
113                 }
114             }
115 
116             if( job.doRequest )
117             {
118                 job.doRequest( job.pThreadSpecificData );
119                 m_nToDo --;
120             }
121             else
122             {
123                 m_nToDo --;
124                 pReturn = job.pThreadSpecificData;
125                 break;
126             }
127         }
128 
129         {
130             // synchronize with the dispose calls
131             MutexGuard guard( m_mutex );
132             m_lstCallstack.pop_front();
133         }
134 
135         return pReturn;
136     }
137 
dispose(sal_Int64 nDisposeId)138     void JobQueue::dispose( sal_Int64 nDisposeId )
139     {
140         MutexGuard guard( m_mutex );
141         for( CallStackList::iterator ii = m_lstCallstack.begin() ;
142              ii != m_lstCallstack.end() ;
143              ++ii )
144         {
145             if( (*ii) == nDisposeId )
146             {
147                 (*ii) = 0;
148             }
149         }
150 
151         if( !m_lstCallstack.empty()  && ! m_lstCallstack.front() )
152         {
153             // The thread is waiting for a disposed pCallerId, let it go
154             osl_setCondition( m_cndWait );
155         }
156     }
157 
suspend()158     void JobQueue::suspend()
159     {
160         MutexGuard guard( m_mutex );
161         m_bSuspended = sal_True;
162     }
163 
resume()164     void JobQueue::resume()
165     {
166         MutexGuard guard( m_mutex );
167         m_bSuspended = sal_False;
168         if( ! m_lstJob.empty() )
169         {
170             osl_setCondition( m_cndWait );
171         }
172     }
173 
isEmpty()174     sal_Bool JobQueue::isEmpty()
175     {
176         MutexGuard guard( m_mutex );
177         return m_lstJob.empty();
178     }
179 
isCallstackEmpty()180     sal_Bool JobQueue::isCallstackEmpty()
181     {
182         MutexGuard guard( m_mutex );
183         return m_lstCallstack.empty();
184     }
185 
isBusy()186     sal_Bool JobQueue::isBusy()
187     {
188         return m_nToDo > 0;
189     }
190 
191 
192 }
193