1*129fa3d1SAndrew Rist /************************************************************** 2cdf0e10cSrcweir * 3*129fa3d1SAndrew Rist * Licensed to the Apache Software Foundation (ASF) under one 4*129fa3d1SAndrew Rist * or more contributor license agreements. See the NOTICE file 5*129fa3d1SAndrew Rist * distributed with this work for additional information 6*129fa3d1SAndrew Rist * regarding copyright ownership. The ASF licenses this file 7*129fa3d1SAndrew Rist * to you under the Apache License, Version 2.0 (the 8*129fa3d1SAndrew Rist * "License"); you may not use this file except in compliance 9*129fa3d1SAndrew Rist * with the License. You may obtain a copy of the License at 10*129fa3d1SAndrew Rist * 11*129fa3d1SAndrew Rist * http://www.apache.org/licenses/LICENSE-2.0 12*129fa3d1SAndrew Rist * 13*129fa3d1SAndrew Rist * Unless required by applicable law or agreed to in writing, 14*129fa3d1SAndrew Rist * software distributed under the License is distributed on an 15*129fa3d1SAndrew Rist * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16*129fa3d1SAndrew Rist * KIND, either express or implied. See the License for the 17*129fa3d1SAndrew Rist * specific language governing permissions and limitations 18*129fa3d1SAndrew Rist * under the License. 19*129fa3d1SAndrew Rist * 20*129fa3d1SAndrew Rist *************************************************************/ 21*129fa3d1SAndrew Rist 22*129fa3d1SAndrew Rist 23cdf0e10cSrcweir 24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove 25cdf0e10cSrcweir #include "precompiled_cppu.hxx" 26cdf0e10cSrcweir #include "jobqueue.hxx" 27cdf0e10cSrcweir #include "threadpool.hxx" 28cdf0e10cSrcweir 29cdf0e10cSrcweir #include <osl/diagnose.h> 30cdf0e10cSrcweir 31cdf0e10cSrcweir using namespace ::osl; 32cdf0e10cSrcweir 33cdf0e10cSrcweir namespace cppu_threadpool { 34cdf0e10cSrcweir JobQueue()35cdf0e10cSrcweir JobQueue::JobQueue() : 36cdf0e10cSrcweir m_nToDo( 0 ), 37cdf0e10cSrcweir m_bSuspended( sal_False ), 38cdf0e10cSrcweir m_cndWait( osl_createCondition() ) 39cdf0e10cSrcweir { 40cdf0e10cSrcweir osl_resetCondition( m_cndWait ); 41cdf0e10cSrcweir m_DisposedCallerAdmin = DisposedCallerAdmin::getInstance(); 42cdf0e10cSrcweir } 43cdf0e10cSrcweir ~JobQueue()44cdf0e10cSrcweir JobQueue::~JobQueue() 45cdf0e10cSrcweir { 46cdf0e10cSrcweir osl_destroyCondition( m_cndWait ); 47cdf0e10cSrcweir } 48cdf0e10cSrcweir 49cdf0e10cSrcweir add(void * pThreadSpecificData,RequestFun * doRequest)50cdf0e10cSrcweir void JobQueue::add( void *pThreadSpecificData, RequestFun * doRequest ) 51cdf0e10cSrcweir { 52cdf0e10cSrcweir MutexGuard guard( m_mutex ); 53cdf0e10cSrcweir Job job = { pThreadSpecificData , doRequest }; 54cdf0e10cSrcweir m_lstJob.push_back( job ); 55cdf0e10cSrcweir if( ! m_bSuspended ) 56cdf0e10cSrcweir { 57cdf0e10cSrcweir osl_setCondition( m_cndWait ); 58cdf0e10cSrcweir } 59cdf0e10cSrcweir m_nToDo ++; 60cdf0e10cSrcweir } 61cdf0e10cSrcweir enter(sal_Int64 nDisposeId,sal_Bool bReturnWhenNoJob)62cdf0e10cSrcweir void *JobQueue::enter( sal_Int64 nDisposeId , sal_Bool bReturnWhenNoJob ) 63cdf0e10cSrcweir { 64cdf0e10cSrcweir void *pReturn = 0; 65cdf0e10cSrcweir { 66cdf0e10cSrcweir // synchronize with the dispose calls 67cdf0e10cSrcweir MutexGuard guard( m_mutex ); 68cdf0e10cSrcweir if( m_DisposedCallerAdmin->isDisposed( nDisposeId ) ) 69cdf0e10cSrcweir { 70cdf0e10cSrcweir return 0; 71cdf0e10cSrcweir } 72cdf0e10cSrcweir m_lstCallstack.push_front( nDisposeId ); 73cdf0e10cSrcweir } 74cdf0e10cSrcweir 75cdf0e10cSrcweir 76cdf0e10cSrcweir while( sal_True ) 77cdf0e10cSrcweir { 78cdf0e10cSrcweir if( bReturnWhenNoJob ) 79cdf0e10cSrcweir { 80cdf0e10cSrcweir MutexGuard guard( m_mutex ); 81cdf0e10cSrcweir if( m_lstJob.empty() ) 82cdf0e10cSrcweir { 83cdf0e10cSrcweir break; 84cdf0e10cSrcweir } 85cdf0e10cSrcweir } 86cdf0e10cSrcweir 87cdf0e10cSrcweir osl_waitCondition( m_cndWait , 0 ); 88cdf0e10cSrcweir 89cdf0e10cSrcweir struct Job job={0,0}; 90cdf0e10cSrcweir { 91cdf0e10cSrcweir // synchronize with add and dispose calls 92cdf0e10cSrcweir MutexGuard guard( m_mutex ); 93cdf0e10cSrcweir 94cdf0e10cSrcweir if( 0 == m_lstCallstack.front() ) 95cdf0e10cSrcweir { 96cdf0e10cSrcweir // disposed ! 97cdf0e10cSrcweir if( m_lstJob.empty() ) 98cdf0e10cSrcweir { 99cdf0e10cSrcweir osl_resetCondition( m_cndWait ); 100cdf0e10cSrcweir } 101cdf0e10cSrcweir break; 102cdf0e10cSrcweir } 103cdf0e10cSrcweir 104cdf0e10cSrcweir OSL_ASSERT( ! m_lstJob.empty() ); 105cdf0e10cSrcweir if( ! m_lstJob.empty() ) 106cdf0e10cSrcweir { 107cdf0e10cSrcweir job = m_lstJob.front(); 108cdf0e10cSrcweir m_lstJob.pop_front(); 109cdf0e10cSrcweir } 110cdf0e10cSrcweir if( m_lstJob.empty() ) 111cdf0e10cSrcweir { 112cdf0e10cSrcweir osl_resetCondition( m_cndWait ); 113cdf0e10cSrcweir } 114cdf0e10cSrcweir } 115cdf0e10cSrcweir 116cdf0e10cSrcweir if( job.doRequest ) 117cdf0e10cSrcweir { 118cdf0e10cSrcweir job.doRequest( job.pThreadSpecificData ); 119cdf0e10cSrcweir m_nToDo --; 120cdf0e10cSrcweir } 121cdf0e10cSrcweir else 122cdf0e10cSrcweir { 123cdf0e10cSrcweir m_nToDo --; 124cdf0e10cSrcweir pReturn = job.pThreadSpecificData; 125cdf0e10cSrcweir break; 126cdf0e10cSrcweir } 127cdf0e10cSrcweir } 128cdf0e10cSrcweir 129cdf0e10cSrcweir { 130cdf0e10cSrcweir // synchronize with the dispose calls 131cdf0e10cSrcweir MutexGuard guard( m_mutex ); 132cdf0e10cSrcweir m_lstCallstack.pop_front(); 133cdf0e10cSrcweir } 134cdf0e10cSrcweir 135cdf0e10cSrcweir return pReturn; 136cdf0e10cSrcweir } 137cdf0e10cSrcweir dispose(sal_Int64 nDisposeId)138cdf0e10cSrcweir void JobQueue::dispose( sal_Int64 nDisposeId ) 139cdf0e10cSrcweir { 140cdf0e10cSrcweir MutexGuard guard( m_mutex ); 141cdf0e10cSrcweir for( CallStackList::iterator ii = m_lstCallstack.begin() ; 142cdf0e10cSrcweir ii != m_lstCallstack.end() ; 143cdf0e10cSrcweir ++ii ) 144cdf0e10cSrcweir { 145cdf0e10cSrcweir if( (*ii) == nDisposeId ) 146cdf0e10cSrcweir { 147cdf0e10cSrcweir (*ii) = 0; 148cdf0e10cSrcweir } 149cdf0e10cSrcweir } 150cdf0e10cSrcweir 151cdf0e10cSrcweir if( !m_lstCallstack.empty() && ! m_lstCallstack.front() ) 152cdf0e10cSrcweir { 153cdf0e10cSrcweir // The thread is waiting for a disposed pCallerId, let it go 154cdf0e10cSrcweir osl_setCondition( m_cndWait ); 155cdf0e10cSrcweir } 156cdf0e10cSrcweir } 157cdf0e10cSrcweir suspend()158cdf0e10cSrcweir void JobQueue::suspend() 159cdf0e10cSrcweir { 160cdf0e10cSrcweir MutexGuard guard( m_mutex ); 161cdf0e10cSrcweir m_bSuspended = sal_True; 162cdf0e10cSrcweir } 163cdf0e10cSrcweir resume()164cdf0e10cSrcweir void JobQueue::resume() 165cdf0e10cSrcweir { 166cdf0e10cSrcweir MutexGuard guard( m_mutex ); 167cdf0e10cSrcweir m_bSuspended = sal_False; 168cdf0e10cSrcweir if( ! m_lstJob.empty() ) 169cdf0e10cSrcweir { 170cdf0e10cSrcweir osl_setCondition( m_cndWait ); 171cdf0e10cSrcweir } 172cdf0e10cSrcweir } 173cdf0e10cSrcweir isEmpty()174cdf0e10cSrcweir sal_Bool JobQueue::isEmpty() 175cdf0e10cSrcweir { 176cdf0e10cSrcweir MutexGuard guard( m_mutex ); 177cdf0e10cSrcweir return m_lstJob.empty(); 178cdf0e10cSrcweir } 179cdf0e10cSrcweir isCallstackEmpty()180cdf0e10cSrcweir sal_Bool JobQueue::isCallstackEmpty() 181cdf0e10cSrcweir { 182cdf0e10cSrcweir MutexGuard guard( m_mutex ); 183cdf0e10cSrcweir return m_lstCallstack.empty(); 184cdf0e10cSrcweir } 185cdf0e10cSrcweir isBusy()186cdf0e10cSrcweir sal_Bool JobQueue::isBusy() 187cdf0e10cSrcweir { 188cdf0e10cSrcweir return m_nToDo > 0; 189cdf0e10cSrcweir } 190cdf0e10cSrcweir 191cdf0e10cSrcweir 192cdf0e10cSrcweir } 193