| /************************************************************** |
| * |
| * 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 <stdio.h> |
| #include <osl/diagnose.h> |
| #include <uno/threadpool.h> |
| |
| #include <rtl/instance.hxx> |
| |
| #include "thread.hxx" |
| #include "jobqueue.hxx" |
| #include "threadpool.hxx" |
| |
| |
| using namespace osl; |
| extern "C" { |
| |
| void SAL_CALL cppu_requestThreadWorker( void *pVoid ) |
| { |
| ::cppu_threadpool::ORequestThread *pThread = ( ::cppu_threadpool::ORequestThread * ) pVoid; |
| |
| pThread->run(); |
| pThread->onTerminated(); |
| } |
| |
| } |
| |
| namespace cppu_threadpool { |
| |
| // ---------------------------------------------------------------------------------- |
| ThreadAdmin::~ThreadAdmin() |
| { |
| #if OSL_DEBUG_LEVEL > 1 |
| if( m_lst.size() ) |
| { |
| fprintf( stderr, "%lu Threads left\n" , static_cast<unsigned long>(m_lst.size()) ); |
| } |
| #endif |
| } |
| |
| void ThreadAdmin::add( ORequestThread *p ) |
| { |
| MutexGuard aGuard( m_mutex ); |
| m_lst.push_back( p ); |
| } |
| |
| void ThreadAdmin::remove( ORequestThread * p ) |
| { |
| MutexGuard aGuard( m_mutex ); |
| ::std::list< ORequestThread * >::iterator ii = ::std::find( m_lst.begin(), m_lst.end(), p ); |
| OSL_ASSERT( ii != m_lst.end() ); |
| m_lst.erase( ii ); |
| } |
| |
| void ThreadAdmin::join() |
| { |
| ORequestThread *pCurrent; |
| do |
| { |
| pCurrent = 0; |
| { |
| MutexGuard aGuard( m_mutex ); |
| if( ! m_lst.empty() ) |
| { |
| pCurrent = m_lst.front(); |
| pCurrent->setDeleteSelf( sal_False ); |
| } |
| } |
| if ( pCurrent ) |
| { |
| pCurrent->join(); |
| delete pCurrent; |
| } |
| } while( pCurrent ); |
| } |
| |
| struct theThreadAdmin : public rtl::StaticWithInit< ThreadAdminHolder, theThreadAdmin > |
| { |
| ThreadAdminHolder operator () () { |
| ThreadAdminHolder aRet(new ThreadAdmin()); |
| return aRet; |
| } |
| }; |
| |
| ThreadAdminHolder& ThreadAdmin::getInstance() |
| { |
| return theThreadAdmin::get(); |
| } |
| |
| // ---------------------------------------------------------------------------------- |
| ORequestThread::ORequestThread( JobQueue *pQueue, |
| const ByteSequence &aThreadId, |
| sal_Bool bAsynchron ) |
| : m_thread( 0 ) |
| , m_aThreadAdmin( ThreadAdmin::getInstance() ) |
| , m_pQueue( pQueue ) |
| , m_aThreadId( aThreadId ) |
| , m_bAsynchron( bAsynchron ) |
| , m_bDeleteSelf( sal_True ) |
| { |
| m_aThreadAdmin->add( this ); |
| } |
| |
| |
| ORequestThread::~ORequestThread() |
| { |
| if (m_thread != 0) |
| { |
| osl_destroyThread(m_thread); |
| } |
| } |
| |
| |
| void ORequestThread::setTask( JobQueue *pQueue, |
| const ByteSequence &aThreadId, |
| sal_Bool bAsynchron ) |
| { |
| m_pQueue = pQueue; |
| m_aThreadId = aThreadId; |
| m_bAsynchron = bAsynchron; |
| } |
| |
| sal_Bool ORequestThread::create() |
| { |
| OSL_ASSERT(m_thread == 0); // only one running thread per instance |
| |
| m_thread = osl_createSuspendedThread( cppu_requestThreadWorker, (void*)this); |
| if ( m_thread ) |
| { |
| osl_resumeThread( m_thread ); |
| } |
| |
| return m_thread != 0; |
| } |
| |
| void ORequestThread::join() |
| { |
| osl_joinWithThread( m_thread ); |
| } |
| |
| void ORequestThread::onTerminated() |
| { |
| m_aThreadAdmin->remove( this ); |
| if( m_bDeleteSelf ) |
| { |
| delete this; |
| } |
| } |
| |
| void ORequestThread::run() |
| { |
| ThreadPoolHolder theThreadPool = cppu_threadpool::ThreadPool::getInstance(); |
| |
| while ( m_pQueue ) |
| { |
| if( ! m_bAsynchron ) |
| { |
| if ( !uno_bindIdToCurrentThread( m_aThreadId.getHandle() ) ) |
| { |
| OSL_ASSERT( false ); |
| } |
| } |
| |
| while( ! m_pQueue->isEmpty() ) |
| { |
| // Note : Oneways should not get a disposable disposeid, |
| // It does not make sense to dispose a call in this state. |
| // That's way we put it an disposeid, that can't be used otherwise. |
| m_pQueue->enter( |
| sal::static_int_cast< sal_Int64 >( |
| reinterpret_cast< sal_IntPtr >(this)), |
| sal_True ); |
| |
| if( m_pQueue->isEmpty() ) |
| { |
| theThreadPool->revokeQueue( m_aThreadId , m_bAsynchron ); |
| // Note : revokeQueue might have failed because m_pQueue.isEmpty() |
| // may be false (race). |
| } |
| } |
| |
| delete m_pQueue; |
| m_pQueue = 0; |
| |
| if( ! m_bAsynchron ) |
| { |
| uno_releaseIdFromCurrentThread(); |
| } |
| |
| theThreadPool->waitInPool( this ); |
| } |
| } |
| } |