diff options
author | Jens-Heiner Rechtien <hr@openoffice.org> | 2000-09-18 14:29:57 +0000 |
---|---|---|
committer | Jens-Heiner Rechtien <hr@openoffice.org> | 2000-09-18 14:29:57 +0000 |
commit | b525a3115f54576017a576ff842dede5e2e3545d (patch) | |
tree | c534b95a9e572b63896467624293a5ca1887d3a3 /cppu/source/threadpool | |
parent | 9399c662f36c385b0c705eb34e636a9aec450282 (diff) |
initial import
Diffstat (limited to 'cppu/source/threadpool')
-rw-r--r-- | cppu/source/threadpool/jobqueue.cxx | 223 | ||||
-rw-r--r-- | cppu/source/threadpool/jobqueue.hxx | 112 | ||||
-rw-r--r-- | cppu/source/threadpool/makefile.mk | 88 | ||||
-rw-r--r-- | cppu/source/threadpool/thread.cxx | 170 | ||||
-rw-r--r-- | cppu/source/threadpool/thread.hxx | 102 | ||||
-rw-r--r-- | cppu/source/threadpool/threadident.cxx | 218 | ||||
-rw-r--r-- | cppu/source/threadpool/threadpool.cxx | 473 | ||||
-rw-r--r-- | cppu/source/threadpool/threadpool.hxx | 163 |
8 files changed, 1549 insertions, 0 deletions
diff --git a/cppu/source/threadpool/jobqueue.cxx b/cppu/source/threadpool/jobqueue.cxx new file mode 100644 index 000000000000..46f263042221 --- /dev/null +++ b/cppu/source/threadpool/jobqueue.cxx @@ -0,0 +1,223 @@ +/************************************************************************* + * + * $RCSfile: jobqueue.cxx,v $ + * + * $Revision: 1.1.1.1 $ + * + * last change: $Author: hr $ $Date: 2000-09-18 15:25:52 $ + * + * The Contents of this file are made available subject to the terms of + * either of the following licenses + * + * - GNU Lesser General Public License Version 2.1 + * - Sun Industry Standards Source License Version 1.1 + * + * Sun Microsystems Inc., October, 2000 + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2000 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + * + * Sun Industry Standards Source License Version 1.1 + * ================================================= + * The contents of this file are subject to the Sun Industry Standards + * Source License Version 1.1 (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.openoffice.org/license.html. + * + * Software provided under this License is provided on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, + * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS, + * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING. + * See the License for the specific provisions governing your rights and + * obligations concerning the Software. + * + * The Initial Developer of the Original Code is: Sun Microsystems, Inc. + * + * Copyright: 2000 by Sun Microsystems, Inc. + * + * All Rights Reserved. + * + * Contributor(s): _______________________________________ + * + * + ************************************************************************/ +#include "jobqueue.hxx" +#include "threadpool.hxx" + +#include <osl/diagnose.h> + +using namespace ::osl; + +namespace cppu_threadpool { + + JobQueue::JobQueue( sal_Bool bAsynchron ) : + m_cndWait( osl_createCondition() ), + m_bSuspended( sal_False ), + m_nToDo( 0 ) + { + osl_resetCondition( m_cndWait ); + } + + JobQueue::~JobQueue() + { + osl_destroyCondition( m_cndWait ); + } + + + void JobQueue::add( void *pThreadSpecificData , + void ( SAL_CALL * doRequest ) ( void *pThreadSpecificData ) ) + { + 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( DisposedCallerAdmin::getInstance()->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 ! + 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; + } + + +} diff --git a/cppu/source/threadpool/jobqueue.hxx b/cppu/source/threadpool/jobqueue.hxx new file mode 100644 index 000000000000..53ba018a71a5 --- /dev/null +++ b/cppu/source/threadpool/jobqueue.hxx @@ -0,0 +1,112 @@ +/************************************************************************* + * + * $RCSfile: jobqueue.hxx,v $ + * + * $Revision: 1.1.1.1 $ + * + * last change: $Author: hr $ $Date: 2000-09-18 15:25:52 $ + * + * The Contents of this file are made available subject to the terms of + * either of the following licenses + * + * - GNU Lesser General Public License Version 2.1 + * - Sun Industry Standards Source License Version 1.1 + * + * Sun Microsystems Inc., October, 2000 + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2000 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + * + * Sun Industry Standards Source License Version 1.1 + * ================================================= + * The contents of this file are subject to the Sun Industry Standards + * Source License Version 1.1 (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.openoffice.org/license.html. + * + * Software provided under this License is provided on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, + * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS, + * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING. + * See the License for the specific provisions governing your rights and + * obligations concerning the Software. + * + * The Initial Developer of the Original Code is: Sun Microsystems, Inc. + * + * Copyright: 2000 by Sun Microsystems, Inc. + * + * All Rights Reserved. + * + * Contributor(s): _______________________________________ + * + * + ************************************************************************/ + +#ifndef _CPPU_THREADPOOL_JOBQUEUE_HXX_ +#define _CPPU_THREADPOOL_JOBQUEUE_HXX_ + +#include <list> + +#include <osl/types.h> +#include <osl/conditn.h> +#include <osl/mutex.hxx> + +namespace cppu_threadpool +{ + struct Job + { + void *pThreadSpecificData; + void ( SAL_CALL *doRequest ) ( void * ); + }; + + typedef ::std::list < struct Job > JobList; + + typedef ::std::list < sal_Int64 > CallStackList; + + class JobQueue + { + public: + JobQueue( sal_Bool bAsynchron ); + ~JobQueue(); + + void add( void *pThreadSpecificData , + void ( SAL_CALL * doRequest ) ( void *pThreadSpecificData ) ); + + void *enter( sal_Int64 nDisposeId , sal_Bool bReturnWhenNoJob = sal_False ); + void dispose( sal_Int64 nDisposeId ); + + void suspend(); + void resume(); + + sal_Bool isEmpty(); + sal_Bool isCallstackEmpty(); + sal_Bool isBusy(); + + private: + ::osl::Mutex m_mutex; + JobList m_lstJob; + CallStackList m_lstCallstack; + sal_Int32 m_nToDo; + sal_Bool m_bSuspended; + oslCondition m_cndWait; + }; +} + +#endif diff --git a/cppu/source/threadpool/makefile.mk b/cppu/source/threadpool/makefile.mk new file mode 100644 index 000000000000..7a82725ba517 --- /dev/null +++ b/cppu/source/threadpool/makefile.mk @@ -0,0 +1,88 @@ +#************************************************************************* +# +# $RCSfile: makefile.mk,v $ +# +# $Revision: 1.1.1.1 $ +# +# last change: $Author: hr $ $Date: 2000-09-18 15:25:52 $ +# +# The Contents of this file are made available subject to the terms of +# either of the following licenses +# +# - GNU Lesser General Public License Version 2.1 +# - Sun Industry Standards Source License Version 1.1 +# +# Sun Microsystems Inc., October, 2000 +# +# GNU Lesser General Public License Version 2.1 +# ============================================= +# Copyright 2000 by Sun Microsystems, Inc. +# 901 San Antonio Road, Palo Alto, CA 94303, USA +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License version 2.1, as published by the Free Software Foundation. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, +# MA 02111-1307 USA +# +# +# Sun Industry Standards Source License Version 1.1 +# ================================================= +# The contents of this file are subject to the Sun Industry Standards +# Source License Version 1.1 (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.openoffice.org/license.html. +# +# Software provided under this License is provided on an "AS IS" basis, +# WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, +# WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS, +# MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING. +# See the License for the specific provisions governing your rights and +# obligations concerning the Software. +# +# The Initial Developer of the Original Code is: Sun Microsystems, Inc. +# +# Copyright: 2000 by Sun Microsystems, Inc. +# +# All Rights Reserved. +# +# Contributor(s): _______________________________________ +# +# +# +#************************************************************************* +PRJ=..$/.. + +PRJNAME=cppu +TARGET=cppu_threadpool + +# --- Settings ----------------------------------------------------- + +.INCLUDE : ..$/..$/util$/makefile.pmk +.INCLUDE : svpre.mk +.INCLUDE : settings.mk +.INCLUDE : sv.mk + +# ------------------------------------------------------------------ + +SLOFILES=\ + $(SLO)$/threadpool.obj\ + $(SLO)$/jobqueue.obj\ + $(SLO)$/thread.obj\ + $(SLO)$/threadident.obj + +# $(SLO)$/threadpool.obj \ +# $(SLO)$/process.obj \ + +# --- Targets ------------------------------------------------------ + +.INCLUDE : ..$/..$/util$/target.pmk +.INCLUDE : target.mk diff --git a/cppu/source/threadpool/thread.cxx b/cppu/source/threadpool/thread.cxx new file mode 100644 index 000000000000..9d006ff142f2 --- /dev/null +++ b/cppu/source/threadpool/thread.cxx @@ -0,0 +1,170 @@ +/************************************************************************* + * + * $RCSfile: thread.cxx,v $ + * + * $Revision: 1.1.1.1 $ + * + * last change: $Author: hr $ $Date: 2000-09-18 15:25:52 $ + * + * The Contents of this file are made available subject to the terms of + * either of the following licenses + * + * - GNU Lesser General Public License Version 2.1 + * - Sun Industry Standards Source License Version 1.1 + * + * Sun Microsystems Inc., October, 2000 + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2000 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + * + * Sun Industry Standards Source License Version 1.1 + * ================================================= + * The contents of this file are subject to the Sun Industry Standards + * Source License Version 1.1 (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.openoffice.org/license.html. + * + * Software provided under this License is provided on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, + * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS, + * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING. + * See the License for the specific provisions governing your rights and + * obligations concerning the Software. + * + * The Initial Developer of the Original Code is: Sun Microsystems, Inc. + * + * Copyright: 2000 by Sun Microsystems, Inc. + * + * All Rights Reserved. + * + * Contributor(s): _______________________________________ + * + * + ************************************************************************/ +#include <stdio.h> +#include <osl/diagnose.h> +#include <uno/threadpool.h> + +#include "thread.hxx" +#include "jobqueue.hxx" +#include "threadpool.hxx" + + +extern "C" { + +void SAL_CALL cppu_requestThreadWorker( void *pVoid ) +{ + ::cppu_threadpool::ORequestThread *pThread = ( ::cppu_threadpool::ORequestThread * ) pVoid; + + pThread->run(); + pThread->onTerminated(); +} + +} +namespace cppu_threadpool { + + ORequestThread::ORequestThread( JobQueue *pQueue, + const ByteSequence &aThreadId, + sal_Bool bAsynchron ) + : m_pQueue( pQueue ) + , m_thread( 0 ) + , m_aThreadId( aThreadId ) + , m_bAsynchron( bAsynchron ) + { + + } + + + ORequestThread::~ORequestThread() + { + if (m_thread != 0) + { + osl_freeThreadHandle(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 + + if ( m_thread = osl_createSuspendedThread( cppu_requestThreadWorker, (void*)this)) + { + osl_resumeThread( m_thread ); + } + + return m_thread != 0; + } + + void ORequestThread::onTerminated() + { + delete this; + } + + // hack during no proper threadlocalstorage support + void SAL_CALL destructCurrentId(); + + void ORequestThread::run() + { + while ( m_pQueue ) + { + if( ! m_bAsynchron ) + { + sal_Bool bReturn = uno_bindIdToCurrentThread( m_aThreadId.getHandle() ); + OSL_ASSERT( bReturn ); + } + + 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_Int64 ) this , sal_True ); + + if( m_pQueue->isEmpty() ) + { + ThreadPool::getInstance()->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(); + } + + cppu_threadpool::ThreadPool::getInstance()->waitInPool( this ); + } + destructCurrentId(); + } +} diff --git a/cppu/source/threadpool/thread.hxx b/cppu/source/threadpool/thread.hxx new file mode 100644 index 000000000000..0099150b71ee --- /dev/null +++ b/cppu/source/threadpool/thread.hxx @@ -0,0 +1,102 @@ +/************************************************************************* + * + * $RCSfile: thread.hxx,v $ + * + * $Revision: 1.1.1.1 $ + * + * last change: $Author: hr $ $Date: 2000-09-18 15:25:52 $ + * + * The Contents of this file are made available subject to the terms of + * either of the following licenses + * + * - GNU Lesser General Public License Version 2.1 + * - Sun Industry Standards Source License Version 1.1 + * + * Sun Microsystems Inc., October, 2000 + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2000 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + * + * Sun Industry Standards Source License Version 1.1 + * ================================================= + * The contents of this file are subject to the Sun Industry Standards + * Source License Version 1.1 (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.openoffice.org/license.html. + * + * Software provided under this License is provided on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, + * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS, + * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING. + * See the License for the specific provisions governing your rights and + * obligations concerning the Software. + * + * The Initial Developer of the Original Code is: Sun Microsystems, Inc. + * + * Copyright: 2000 by Sun Microsystems, Inc. + * + * All Rights Reserved. + * + * Contributor(s): _______________________________________ + * + * + ************************************************************************/ +#ifndef _CPPU_THREADPOOL_THREAD_HXX +#define _CPPU_THREADPOOL_THREAD_HXX + +#include <osl/types.h> +#include <osl/thread.h> + +#include "jobqueue.hxx" + +namespace cppu_threadpool { + + class JobQueue; + + //----------------------------------------- + // private thread class for the threadpool + // independent from vos + //----------------------------------------- + class ORequestThread + { + public: + ORequestThread( JobQueue * , + const ::rtl::ByteSequence &aThreadId, + sal_Bool bAsynchron ); + ~ORequestThread(); + + void setTask( JobQueue * , const ::rtl::ByteSequence & aThreadId , sal_Bool bAsynchron ); + + sal_Bool create(); + void onTerminated(); + void run(); + + private: + oslThread m_thread; + JobQueue *m_pQueue; + ::rtl::ByteSequence m_aThreadId; + sal_Bool m_bAsynchron; + }; + +} // end cppu_threadpool + + +#endif + diff --git a/cppu/source/threadpool/threadident.cxx b/cppu/source/threadpool/threadident.cxx new file mode 100644 index 000000000000..cedf69b6e869 --- /dev/null +++ b/cppu/source/threadpool/threadident.cxx @@ -0,0 +1,218 @@ +/************************************************************************* + * + * $RCSfile: threadident.cxx,v $ + * + * $Revision: 1.1.1.1 $ + * + * last change: $Author: hr $ $Date: 2000-09-18 15:25:52 $ + * + * The Contents of this file are made available subject to the terms of + * either of the following licenses + * + * - GNU Lesser General Public License Version 2.1 + * - Sun Industry Standards Source License Version 1.1 + * + * Sun Microsystems Inc., October, 2000 + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2000 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + * + * Sun Industry Standards Source License Version 1.1 + * ================================================= + * The contents of this file are subject to the Sun Industry Standards + * Source License Version 1.1 (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.openoffice.org/license.html. + * + * Software provided under this License is provided on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, + * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS, + * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING. + * See the License for the specific provisions governing your rights and + * obligations concerning the Software. + * + * The Initial Developer of the Original Code is: Sun Microsystems, Inc. + * + * Copyright: 2000 by Sun Microsystems, Inc. + * + * All Rights Reserved. + * + * Contributor(s): _______________________________________ + * + * + ************************************************************************/ +#include <stdio.h> +#include <assert.h> + +#include <list> +#include <hash_map> + +#include <osl/mutex.hxx> +#include <osl/thread.h> +#include <osl/diagnose.h> + +#include <rtl/process.h> +#include <rtl/byteseq.hxx> + +#include <uno/threadpool.h> + +#include <com/sun/star/uno/Sequence.hxx> + +using namespace ::std; +using namespace ::osl; +using namespace ::rtl; + + +static sal_Bool g_bInitialized; +static oslThreadKey g_key; + +namespace cppu_threadpool +{ +struct IdContainer +{ + sal_Sequence *pLocalThreadId; + sal_Int32 nRefCountOfCurrentId; + sal_Sequence *pCurrentId; +}; +} +using namespace cppu_threadpool; + +static inline oslThreadKey getKey() +{ + if( ! g_bInitialized ) + { + ::osl::MutexGuard guard( ::osl::Mutex::getGlobalMutex() ); + if( ! g_bInitialized ) + { + g_key = osl_createThreadKey(); + g_bInitialized = sal_True; + } + } + return g_key; +} + +static inline void createLocalId( sal_Sequence **ppThreadId ) +{ + rtl_byte_sequence_constructNoDefault( ppThreadId , 4 + 16 ); + *((sal_Int32*) ((*ppThreadId)->elements)) = osl_getThreadIdentifier(0); + + rtl_getGlobalProcessId( (sal_uInt8 * ) &( (*ppThreadId)->elements[4]) ); +} + + +static void SAL_CALL destructIdContainer( void *p ) +{ + if( p ) + { + IdContainer *pId = (IdContainer * ) p; + rtl_byte_sequence_release( pId->pLocalThreadId ); + rtl_byte_sequence_release( pId->pCurrentId ); + rtl_freeMemory( p ); + } +} + + +//-------------------------------------------------------- +// private hack as long as no proper threadlocal storage is provided +//-------------------------------------------------------- +namespace cppu_threadpool { +void SAL_CALL destructCurrentId() +{ + destructIdContainer( osl_getThreadKeyData( getKey() ) ); +} +} + + +extern "C" SAL_DLLEXPORT void SAL_CALL +uno_getIdOfCurrentThread( sal_Sequence **ppThreadId ) +{ + IdContainer * p = (IdContainer * ) osl_getThreadKeyData( getKey() ); + if( ! p ) + { + // first time, that the thread enters the bridge + createLocalId( ppThreadId ); + + // TODO + // note : this is a leak ! + IdContainer *p = (IdContainer *) rtl_allocateMemory( sizeof( IdContainer ) ); + p->pLocalThreadId = *ppThreadId; + p->pCurrentId = *ppThreadId; + p->nRefCountOfCurrentId = 1; + rtl_byte_sequence_acquire( p->pLocalThreadId ); + rtl_byte_sequence_acquire( p->pCurrentId ); + + OSL_VERIFY( osl_setThreadKeyData( getKey(), p ) ); + } + else + { + p->nRefCountOfCurrentId ++; + if( *ppThreadId ) + { + rtl_byte_sequence_release( *ppThreadId ); + } + *ppThreadId = p->pCurrentId; + rtl_byte_sequence_acquire( *ppThreadId ); + } +} + + +extern "C" SAL_DLLEXPORT void SAL_CALL uno_releaseIdFromCurrentThread() +{ + IdContainer *p = (IdContainer * ) osl_getThreadKeyData( getKey() ); + OSL_ASSERT( p ); + OSL_ASSERT( p->nRefCountOfCurrentId ); + + p->nRefCountOfCurrentId --; + if( ! p->nRefCountOfCurrentId && (p->pLocalThreadId != p->pCurrentId) ) + { + rtl_byte_sequence_assign( &(p->pCurrentId) , p->pLocalThreadId ); + } +} + +extern "C" SAL_DLLEXPORT sal_Bool SAL_CALL uno_bindIdToCurrentThread( sal_Sequence *pThreadId ) +{ + IdContainer *p = (IdContainer * ) osl_getThreadKeyData( getKey() ); + if( ! p ) + { + IdContainer *p = (IdContainer * ) rtl_allocateMemory( sizeof( IdContainer ) ); + + p->pLocalThreadId = 0; + createLocalId( &(p->pLocalThreadId) ); + p->nRefCountOfCurrentId = 1; + p->pCurrentId = pThreadId; + rtl_byte_sequence_acquire( p->pCurrentId ); + osl_setThreadKeyData( getKey() , p ); + } + else + { + OSL_ASSERT( 0 == p->nRefCountOfCurrentId ); + if( 0 == p->nRefCountOfCurrentId ) + { + rtl_byte_sequence_assign(&( p->pCurrentId ), pThreadId ); + p->nRefCountOfCurrentId ++; + } + else + { + return sal_False; + } + + } + return sal_True; +} diff --git a/cppu/source/threadpool/threadpool.cxx b/cppu/source/threadpool/threadpool.cxx new file mode 100644 index 000000000000..7133eeb149e3 --- /dev/null +++ b/cppu/source/threadpool/threadpool.cxx @@ -0,0 +1,473 @@ +/************************************************************************* + * + * $RCSfile: threadpool.cxx,v $ + * + * $Revision: 1.1.1.1 $ + * + * last change: $Author: hr $ $Date: 2000-09-18 15:25:52 $ + * + * The Contents of this file are made available subject to the terms of + * either of the following licenses + * + * - GNU Lesser General Public License Version 2.1 + * - Sun Industry Standards Source License Version 1.1 + * + * Sun Microsystems Inc., October, 2000 + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2000 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + * + * Sun Industry Standards Source License Version 1.1 + * ================================================= + * The contents of this file are subject to the Sun Industry Standards + * Source License Version 1.1 (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.openoffice.org/license.html. + * + * Software provided under this License is provided on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, + * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS, + * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING. + * See the License for the specific provisions governing your rights and + * obligations concerning the Software. + * + * The Initial Developer of the Original Code is: Sun Microsystems, Inc. + * + * Copyright: 2000 by Sun Microsystems, Inc. + * + * All Rights Reserved. + * + * Contributor(s): _______________________________________ + * + * + ************************************************************************/ + +#include <stdio.h> + +#include <osl/diagnose.h> +#include <osl/mutex.hxx> +#include <osl/thread.h> + +#include <uno/threadpool.h> + +#include "threadpool.hxx" +#include "thread.hxx" + +using namespace ::std; +using namespace ::osl; + +struct uno_threadpool_Handle +{ + /** + * Global Threadidentifier of the waiting thread + **/ + uno_threadpool_Handle( const ByteSequence &aThreadId_ , sal_Int64 nDisposeId_ ) + : aThreadId( aThreadId_ ) + , nDisposeId( nDisposeId_ ) + {} + + ByteSequence aThreadId; + sal_Int64 nDisposeId; +}; + +namespace cppu_threadpool +{ + DisposedCallerAdmin *DisposedCallerAdmin::getInstance() + { + static DisposedCallerAdmin *pDisposedCallerAdmin = 0; + if( ! pDisposedCallerAdmin ) + { + MutexGuard guard( Mutex::getGlobalMutex() ); + if( ! pDisposedCallerAdmin ) + { + static DisposedCallerAdmin admin; + pDisposedCallerAdmin = &admin; + } + } + return pDisposedCallerAdmin; + } + + DisposedCallerAdmin::~DisposedCallerAdmin() + { +#ifdef DEBUG + if( !m_lst.empty() ) + { + printf( "DisposedCallerList : %d left\n" , m_lst.size( )); + } +#endif + } + + void DisposedCallerAdmin::dispose( sal_Int64 nDisposeId ) + { + MutexGuard guard( m_mutex ); + m_lst.push_back( nDisposeId ); + } + + void DisposedCallerAdmin::stopDisposing( sal_Int64 nDisposeId ) + { + MutexGuard guard( m_mutex ); + for( DisposedCallerList::iterator ii = m_lst.begin() ; + ii != m_lst.end() ; + ++ ii ) + { + if( (*ii) == nDisposeId ) + { + m_lst.erase( ii ); + break; + } + } + } + + sal_Bool DisposedCallerAdmin::isDisposed( sal_Int64 nDisposeId ) + { + MutexGuard guard( m_mutex ); + for( DisposedCallerList::iterator ii = m_lst.begin() ; + ii != m_lst.end() ; + ++ ii ) + { + if( (*ii) == nDisposeId ) + { + return sal_True; + } + } + return sal_False; + } + + + //------------------------------------------------------------------------------- + ThreadPool::~ThreadPool() + { +#ifdef DEBUG + if( m_mapQueue.size() ) + { + printf( "ThreadIdHashMap : %d left\n" , m_mapQueue.size() ); + } +#endif + } + ThreadPool *ThreadPool::getInstance() + { + static ThreadPool *pThreadPool = 0; + if( ! pThreadPool ) + { + MutexGuard guard( Mutex::getGlobalMutex() ); + if( ! pThreadPool ) + { + static ThreadPool pool; + pThreadPool = &pool; + } + } + return pThreadPool; + } + + + void ThreadPool::dispose( sal_Int64 nDisposeId ) + { + DisposedCallerAdmin::getInstance()->dispose( nDisposeId ); + + MutexGuard guard( m_mutex ); + for( ThreadIdHashMap::iterator ii = m_mapQueue.begin() ; + ii != m_mapQueue.end(); + ++ii) + { + if( (*ii).second.first ) + { + (*ii).second.first->dispose( nDisposeId ); + } + if( (*ii).second.second ) + { + (*ii).second.second->dispose( nDisposeId ); + } + } + } + + void ThreadPool::stopDisposing( sal_Int64 nDisposeId ) + { + DisposedCallerAdmin::getInstance()->stopDisposing( nDisposeId ); + } + + /****************** + * This methods lets the thread wait a certain amount of time. If within this timespan + * a new request comes in, this thread is reused. This is done only to improve performance, + * it is not required for threadpool functionality. + ******************/ + void ThreadPool::waitInPool( ORequestThread * pThread ) + { + struct WaitingThread waitingThread; + waitingThread.condition = osl_createCondition(); + waitingThread.thread = pThread; + { + MutexGuard guard( m_mutexWaitingThreadList ); + m_lstThreads.push_front( &waitingThread ); + } + + // let the thread wait 2 seconds + osl_resetCondition( waitingThread.condition ); + TimeValue time = { 2 , 0 }; + osl_waitCondition( waitingThread.condition , &time ); + + { + MutexGuard guard ( m_mutexWaitingThreadList ); + if( waitingThread.thread ) + { + // thread wasn't reused, remove it from the list + WaitingThreadList::iterator ii = find( + m_lstThreads.begin(), m_lstThreads.end(), &waitingThread ); + OSL_ASSERT( ii != m_lstThreads.end() ); + m_lstThreads.erase( ii ); + } + } + + osl_destroyCondition( waitingThread.condition ); + } + + void ThreadPool::createThread( JobQueue *pQueue , + const ByteSequence &aThreadId, + sal_Bool bAsynchron ) + { + sal_Bool bCreate = sal_True; + { + // Can a thread be reused ? + MutexGuard guard( m_mutexWaitingThreadList ); + if( ! m_lstThreads.empty() ) + { + // inform the thread and let it go + struct WaitingThread *pWaitingThread = m_lstThreads.back(); + pWaitingThread->thread->setTask( pQueue , aThreadId , bAsynchron ); + pWaitingThread->thread = 0; + + // remove from list + m_lstThreads.pop_back(); + + // let the thread go + osl_setCondition( pWaitingThread->condition ); + bCreate = sal_False; + } + } + + if( bCreate ) + { + ORequestThread *pThread = + new ORequestThread( pQueue , aThreadId, bAsynchron); + // deletes itself ! + pThread->create(); + } + } + + sal_Bool ThreadPool::revokeQueue( const ByteSequence &aThreadId, sal_Bool bAsynchron ) + { + MutexGuard guard( m_mutex ); + + ThreadIdHashMap::iterator ii = m_mapQueue.find( aThreadId ); + OSL_ASSERT( ii != m_mapQueue.end() ); + + if( bAsynchron ) + { + if( ! (*ii).second.second->isEmpty() ) + { + // another thread has put something into the queue + return sal_False; + } + + (*ii).second.second = 0; + if( (*ii).second.first ) + { + // all oneway request have been processed, now + // synchronus requests may go on + (*ii).second.first->resume(); + } + } + else + { + if( ! (*ii).second.first->isEmpty() ) + { + // another thread has put something into the queue + return sal_False; + } + (*ii).second.first = 0; + } + + if( 0 == (*ii).second.first && 0 == (*ii).second.second ) + { + m_mapQueue.erase( ii ); + } + + return sal_True; + } + + + void ThreadPool::addJob( + const ByteSequence &aThreadId , + sal_Bool bAsynchron, + void *pThreadSpecificData, + void ( SAL_CALL * doRequest ) ( void * ) ) + { + sal_Bool bCreateThread = sal_False; + JobQueue *pQueue = 0; + { + MutexGuard guard( m_mutex ); + + ThreadIdHashMap::iterator ii = m_mapQueue.find( aThreadId ); + + if( ii == m_mapQueue.end() ) + { + m_mapQueue[ aThreadId ] = pair < JobQueue * , JobQueue * > ( 0 , 0 ); + ii = m_mapQueue.find( aThreadId ); + OSL_ASSERT( ii != m_mapQueue.end() ); + } + + if( bAsynchron ) + { + if( ! (*ii).second.second ) + { + (*ii).second.second = new JobQueue( bAsynchron ); + bCreateThread = sal_True; + } + pQueue = (*ii).second.second; + } + else + { + if( ! (*ii).second.first ) + { + (*ii).second.first = new JobQueue( bAsynchron ); + bCreateThread = sal_True; + } + pQueue = (*ii).second.first; + + if( (*ii).second.second && ( (*ii).second.second->isBusy() ) ) + { + pQueue->suspend(); + } + } + pQueue->add( pThreadSpecificData , doRequest ); + } + + if( bCreateThread ) + { + createThread( pQueue , aThreadId , bAsynchron); + } + } + + void ThreadPool::prepare( const ByteSequence &aThreadId ) + { + MutexGuard guard( m_mutex ); + + ThreadIdHashMap::iterator ii = m_mapQueue.find( aThreadId ); + + if( ii == m_mapQueue.end() ) + { + JobQueue *p = new JobQueue( sal_False ); + m_mapQueue[ aThreadId ] = pair< JobQueue * , JobQueue * > ( p , 0 ); + } + else if( 0 == (*ii).second.first ) + { + (*ii).second.first = new JobQueue( sal_False ); + } + } + + void * ThreadPool::enter( const ByteSequence & aThreadId , sal_Int64 nDisposeId ) + { + JobQueue *pQueue = 0; + { + MutexGuard guard( m_mutex ); + + ThreadIdHashMap::iterator ii = m_mapQueue.find( aThreadId ); + + OSL_ASSERT( ii != m_mapQueue.end() ); + pQueue = (*ii).second.first; + } + + OSL_ASSERT( pQueue ); + void *pReturn = pQueue->enter( nDisposeId ); + + if( pQueue->isCallstackEmpty() ) + { + if( revokeQueue( aThreadId , sal_False) ) + { + // remove queue + delete pQueue; + } + } + return pReturn; + } +} + + +using namespace cppu_threadpool; + + +//------------------------------ +// +// The C-Interface +// +//------------------------------- +extern "C" SAL_DLLEXPORT void SAL_CALL uno_threadpool_putRequest( + sal_Sequence *pThreadId, void *pThreadSpecificData, + void ( SAL_CALL * doRequest ) ( void *pThreadSpecificData ), sal_Bool bIsOneway ) +{ + ThreadPool::getInstance()->addJob( pThreadId, bIsOneway, pThreadSpecificData,doRequest ); +} + + + +extern "C" SAL_DLLEXPORT void SAL_CALL uno_threadpool_putReply( + sal_Sequence *pThreadId, void *pThreadSpecificData ) +{ + ThreadPool::getInstance()->addJob( pThreadId, sal_False, pThreadSpecificData, 0 ); +} + + +extern "C" SAL_DLLEXPORT struct uno_threadpool_Handle * SAL_CALL +uno_threadpool_createHandle( sal_Int64 nDisposeId ) +{ + sal_Sequence *pThreadId = 0; + uno_getIdOfCurrentThread( &pThreadId ); + + struct uno_threadpool_Handle *pHandle = new uno_threadpool_Handle( pThreadId, nDisposeId ); + ThreadPool::getInstance()->prepare( pThreadId ); + + rtl_byte_sequence_release( pThreadId ); + + return pHandle; +} + +extern "C" SAL_DLLEXPORT void SAL_CALL uno_threadpool_enter( + struct uno_threadpool_Handle *pHandle , void **ppThreadSpecificData ) +{ + OSL_ASSERT( ppThreadSpecificData ); + + *ppThreadSpecificData = + ThreadPool::getInstance()->enter( pHandle->aThreadId , pHandle->nDisposeId ); + + uno_releaseIdFromCurrentThread(); + delete pHandle; +} + + +extern "C" SAL_DLLEXPORT void SAL_CALL +uno_threadpool_disposeThreads( sal_Int64 nDisposeId ) +{ + ThreadPool::getInstance()->dispose( nDisposeId ); +} + +extern "C" SAL_DLLEXPORT void SAL_CALL +uno_threadpool_stopDisposeThreads( sal_Int64 nDisposeId ) +{ + ThreadPool::getInstance()->stopDisposing( nDisposeId ); +} diff --git a/cppu/source/threadpool/threadpool.hxx b/cppu/source/threadpool/threadpool.hxx new file mode 100644 index 000000000000..46b822b8b09b --- /dev/null +++ b/cppu/source/threadpool/threadpool.hxx @@ -0,0 +1,163 @@ +/************************************************************************* + * + * $RCSfile: threadpool.hxx,v $ + * + * $Revision: 1.1.1.1 $ + * + * last change: $Author: hr $ $Date: 2000-09-18 15:25:52 $ + * + * The Contents of this file are made available subject to the terms of + * either of the following licenses + * + * - GNU Lesser General Public License Version 2.1 + * - Sun Industry Standards Source License Version 1.1 + * + * Sun Microsystems Inc., October, 2000 + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2000 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + * + * Sun Industry Standards Source License Version 1.1 + * ================================================= + * The contents of this file are subject to the Sun Industry Standards + * Source License Version 1.1 (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.openoffice.org/license.html. + * + * Software provided under this License is provided on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, + * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS, + * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING. + * See the License for the specific provisions governing your rights and + * obligations concerning the Software. + * + * The Initial Developer of the Original Code is: Sun Microsystems, Inc. + * + * Copyright: 2000 by Sun Microsystems, Inc. + * + * All Rights Reserved. + * + * Contributor(s): _______________________________________ + * + * + ************************************************************************/ +#include <hash_map> + +#include <osl/conditn.h> + +#include <rtl/byteseq.hxx> + +#include "jobqueue.hxx" + + +using namespace ::rtl; +namespace cppu_threadpool { + class ORequestThread; + + struct EqualThreadId + { + sal_Int32 operator () ( const ::rtl::ByteSequence &a , const ::rtl::ByteSequence &b ) const + { + return a == b; + } + }; + + struct HashThreadId + { + sal_Int32 operator () ( const ::rtl::ByteSequence &a ) const + { + if( a.getLength() >= 4 ) + { + return *(sal_Int32 *)a.getConstArray(); + } + return 0; + } + }; + + typedef ::std::hash_map + < + ByteSequence, // ThreadID + ::std::pair < JobQueue * , JobQueue * >, + HashThreadId, + EqualThreadId + > ThreadIdHashMap; + + typedef ::std::list < sal_Int64 > DisposedCallerList; + + + struct WaitingThread + { + oslCondition condition; + ORequestThread *thread; + }; + + typedef ::std::list < struct ::cppu_threadpool::WaitingThread * > WaitingThreadList; + + class DisposedCallerAdmin + { + public: + ~DisposedCallerAdmin(); + + static DisposedCallerAdmin *getInstance(); + + void dispose( sal_Int64 nDisposeId ); + void stopDisposing( sal_Int64 nDisposeId ); + sal_Bool isDisposed( sal_Int64 nDisposeId ); + + private: + ::osl::Mutex m_mutex; + DisposedCallerList m_lst; + }; + + class ThreadPool + { + public: + ~ThreadPool(); + static ThreadPool *getInstance(); + + void dispose( sal_Int64 nDisposeId ); + void stopDisposing( sal_Int64 nDisposeId ); + + void addJob( const ByteSequence &aThreadId, + sal_Bool bAsynchron, + void *pThreadSpecificData, + void ( SAL_CALL * doRequest ) ( void * ) ); + + void prepare( const ByteSequence &aThreadId ); + void * enter( const ByteSequence &aThreadId, sal_Int64 nDisposeId ); + + /******** + * @return true, if queue could be succesfully revoked. + ********/ + sal_Bool revokeQueue( const ByteSequence & aThreadId , sal_Bool bAsynchron ); + + void waitInPool( ORequestThread *pThread ); + private: + void createThread( JobQueue *pQueue, const ByteSequence &aThreadId, sal_Bool bAsynchron); + + + ThreadIdHashMap m_mapQueue; + ::osl::Mutex m_mutex; + + ::osl::Mutex m_mutexWaitingThreadList; + WaitingThreadList m_lstThreads; + }; + +} // end namespace cppu_threadpool |