xref: /trunk/main/cppu/source/threadpool/jobqueue.cxx (revision cdf0e10c4e3984b49a9502b011690b615761d4a3)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_cppu.hxx"
30 #include "jobqueue.hxx"
31 #include "threadpool.hxx"
32 
33 #include <osl/diagnose.h>
34 
35 using namespace ::osl;
36 
37 namespace cppu_threadpool {
38 
39     JobQueue::JobQueue() :
40         m_nToDo( 0 ),
41         m_bSuspended( sal_False ),
42         m_cndWait( osl_createCondition() )
43     {
44         osl_resetCondition( m_cndWait );
45         m_DisposedCallerAdmin = DisposedCallerAdmin::getInstance();
46     }
47 
48     JobQueue::~JobQueue()
49     {
50         osl_destroyCondition( m_cndWait );
51     }
52 
53 
54     void JobQueue::add( void *pThreadSpecificData, RequestFun * doRequest )
55     {
56         MutexGuard guard( m_mutex );
57         Job job = { pThreadSpecificData , doRequest };
58         m_lstJob.push_back( job );
59         if( ! m_bSuspended )
60         {
61             osl_setCondition( m_cndWait );
62         }
63         m_nToDo ++;
64     }
65 
66     void *JobQueue::enter( sal_Int64 nDisposeId , sal_Bool bReturnWhenNoJob )
67     {
68         void *pReturn = 0;
69         {
70             // synchronize with the dispose calls
71             MutexGuard guard( m_mutex );
72             if( m_DisposedCallerAdmin->isDisposed( nDisposeId ) )
73             {
74                 return 0;
75             }
76             m_lstCallstack.push_front( nDisposeId );
77         }
78 
79 
80         while( sal_True )
81         {
82             if( bReturnWhenNoJob )
83             {
84                 MutexGuard guard( m_mutex );
85                 if( m_lstJob.empty() )
86                 {
87                     break;
88                 }
89             }
90 
91             osl_waitCondition( m_cndWait , 0 );
92 
93             struct Job job={0,0};
94             {
95                 // synchronize with add and dispose calls
96                 MutexGuard guard( m_mutex );
97 
98                 if( 0 == m_lstCallstack.front() )
99                 {
100                     // disposed !
101                     if( m_lstJob.empty() )
102                     {
103                         osl_resetCondition( m_cndWait );
104                     }
105                     break;
106                 }
107 
108                 OSL_ASSERT( ! m_lstJob.empty() );
109                 if( ! m_lstJob.empty() )
110                 {
111                     job = m_lstJob.front();
112                     m_lstJob.pop_front();
113                 }
114                 if( m_lstJob.empty() )
115                 {
116                     osl_resetCondition( m_cndWait );
117                 }
118             }
119 
120             if( job.doRequest )
121             {
122                 job.doRequest( job.pThreadSpecificData );
123                 m_nToDo --;
124             }
125             else
126             {
127                 m_nToDo --;
128                 pReturn = job.pThreadSpecificData;
129                 break;
130             }
131         }
132 
133         {
134             // synchronize with the dispose calls
135             MutexGuard guard( m_mutex );
136             m_lstCallstack.pop_front();
137         }
138 
139         return pReturn;
140     }
141 
142     void JobQueue::dispose( sal_Int64 nDisposeId )
143     {
144         MutexGuard guard( m_mutex );
145         for( CallStackList::iterator ii = m_lstCallstack.begin() ;
146              ii != m_lstCallstack.end() ;
147              ++ii )
148         {
149             if( (*ii) == nDisposeId )
150             {
151                 (*ii) = 0;
152             }
153         }
154 
155         if( !m_lstCallstack.empty()  && ! m_lstCallstack.front() )
156         {
157             // The thread is waiting for a disposed pCallerId, let it go
158             osl_setCondition( m_cndWait );
159         }
160     }
161 
162     void JobQueue::suspend()
163     {
164         MutexGuard guard( m_mutex );
165         m_bSuspended = sal_True;
166     }
167 
168     void JobQueue::resume()
169     {
170         MutexGuard guard( m_mutex );
171         m_bSuspended = sal_False;
172         if( ! m_lstJob.empty() )
173         {
174             osl_setCondition( m_cndWait );
175         }
176     }
177 
178     sal_Bool JobQueue::isEmpty()
179     {
180         MutexGuard guard( m_mutex );
181         return m_lstJob.empty();
182     }
183 
184     sal_Bool JobQueue::isCallstackEmpty()
185     {
186         MutexGuard guard( m_mutex );
187         return m_lstCallstack.empty();
188     }
189 
190     sal_Bool JobQueue::isBusy()
191     {
192         return m_nToDo > 0;
193     }
194 
195 
196 }
197