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