/************************************************************** * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * *************************************************************/ // MARKER(update_precomp.py): autogen include statement, do not remove #include "precompiled_cppu.hxx" #include "jobqueue.hxx" #include "threadpool.hxx" #include using namespace ::osl; namespace cppu_threadpool { JobQueue::JobQueue() : m_nToDo( 0 ), m_bSuspended( sal_False ), m_cndWait( osl_createCondition() ) { osl_resetCondition( m_cndWait ); m_DisposedCallerAdmin = DisposedCallerAdmin::getInstance(); } JobQueue::~JobQueue() { osl_destroyCondition( m_cndWait ); } void JobQueue::add( void *pThreadSpecificData, RequestFun * doRequest ) { MutexGuard guard( m_mutex ); Job job = { pThreadSpecificData , doRequest }; m_lstJob.push_back( job ); if( ! m_bSuspended ) { osl_setCondition( m_cndWait ); } m_nToDo ++; } void *JobQueue::enter( sal_Int64 nDisposeId , sal_Bool bReturnWhenNoJob ) { void *pReturn = 0; { // synchronize with the dispose calls MutexGuard guard( m_mutex ); if( m_DisposedCallerAdmin->isDisposed( nDisposeId ) ) { return 0; } m_lstCallstack.push_front( nDisposeId ); } while( sal_True ) { if( bReturnWhenNoJob ) { MutexGuard guard( m_mutex ); if( m_lstJob.empty() ) { break; } } osl_waitCondition( m_cndWait , 0 ); struct Job job={0,0}; { // synchronize with add and dispose calls MutexGuard guard( m_mutex ); if( 0 == m_lstCallstack.front() ) { // disposed ! if( m_lstJob.empty() ) { osl_resetCondition( m_cndWait ); } break; } OSL_ASSERT( ! m_lstJob.empty() ); if( ! m_lstJob.empty() ) { job = m_lstJob.front(); m_lstJob.pop_front(); } if( m_lstJob.empty() ) { osl_resetCondition( m_cndWait ); } } if( job.doRequest ) { job.doRequest( job.pThreadSpecificData ); m_nToDo --; } else { m_nToDo --; pReturn = job.pThreadSpecificData; break; } } { // synchronize with the dispose calls MutexGuard guard( m_mutex ); m_lstCallstack.pop_front(); } return pReturn; } void JobQueue::dispose( sal_Int64 nDisposeId ) { MutexGuard guard( m_mutex ); for( CallStackList::iterator ii = m_lstCallstack.begin() ; ii != m_lstCallstack.end() ; ++ii ) { if( (*ii) == nDisposeId ) { (*ii) = 0; } } if( !m_lstCallstack.empty() && ! m_lstCallstack.front() ) { // The thread is waiting for a disposed pCallerId, let it go osl_setCondition( m_cndWait ); } } void JobQueue::suspend() { MutexGuard guard( m_mutex ); m_bSuspended = sal_True; } void JobQueue::resume() { MutexGuard guard( m_mutex ); m_bSuspended = sal_False; if( ! m_lstJob.empty() ) { osl_setCondition( m_cndWait ); } } sal_Bool JobQueue::isEmpty() { MutexGuard guard( m_mutex ); return m_lstJob.empty(); } sal_Bool JobQueue::isCallstackEmpty() { MutexGuard guard( m_mutex ); return m_lstCallstack.empty(); } sal_Bool JobQueue::isBusy() { return m_nToDo > 0; } }