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 <hash_set>
27cdf0e10cSrcweir #include <stdio.h>
28cdf0e10cSrcweir
29cdf0e10cSrcweir #include <osl/diagnose.h>
30cdf0e10cSrcweir #include <osl/mutex.hxx>
31cdf0e10cSrcweir #include <osl/thread.h>
32cdf0e10cSrcweir #include <rtl/instance.hxx>
33cdf0e10cSrcweir
34cdf0e10cSrcweir #include <uno/threadpool.h>
35cdf0e10cSrcweir
36cdf0e10cSrcweir #include "threadpool.hxx"
37cdf0e10cSrcweir #include "thread.hxx"
38cdf0e10cSrcweir
39cdf0e10cSrcweir using namespace ::std;
40cdf0e10cSrcweir using namespace ::osl;
41cdf0e10cSrcweir
42cdf0e10cSrcweir namespace cppu_threadpool
43cdf0e10cSrcweir {
44cdf0e10cSrcweir struct theDisposedCallerAdmin :
45cdf0e10cSrcweir public rtl::StaticWithInit< DisposedCallerAdminHolder, theDisposedCallerAdmin >
46cdf0e10cSrcweir {
operator ()cppu_threadpool::theDisposedCallerAdmin47cdf0e10cSrcweir DisposedCallerAdminHolder operator () () {
48cdf0e10cSrcweir return DisposedCallerAdminHolder(new DisposedCallerAdmin());
49cdf0e10cSrcweir }
50cdf0e10cSrcweir };
51cdf0e10cSrcweir
getInstance()52cdf0e10cSrcweir DisposedCallerAdminHolder DisposedCallerAdmin::getInstance()
53cdf0e10cSrcweir {
54cdf0e10cSrcweir return theDisposedCallerAdmin::get();
55cdf0e10cSrcweir }
56cdf0e10cSrcweir
~DisposedCallerAdmin()57cdf0e10cSrcweir DisposedCallerAdmin::~DisposedCallerAdmin()
58cdf0e10cSrcweir {
59cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1
60cdf0e10cSrcweir if( !m_lst.empty() )
61cdf0e10cSrcweir {
62cdf0e10cSrcweir printf( "DisposedCallerList : %lu left\n" , static_cast<unsigned long>(m_lst.size( )));
63cdf0e10cSrcweir }
64cdf0e10cSrcweir #endif
65cdf0e10cSrcweir }
66cdf0e10cSrcweir
dispose(sal_Int64 nDisposeId)67cdf0e10cSrcweir void DisposedCallerAdmin::dispose( sal_Int64 nDisposeId )
68cdf0e10cSrcweir {
69cdf0e10cSrcweir MutexGuard guard( m_mutex );
70cdf0e10cSrcweir m_lst.push_back( nDisposeId );
71cdf0e10cSrcweir }
72cdf0e10cSrcweir
stopDisposing(sal_Int64 nDisposeId)73cdf0e10cSrcweir void DisposedCallerAdmin::stopDisposing( sal_Int64 nDisposeId )
74cdf0e10cSrcweir {
75cdf0e10cSrcweir MutexGuard guard( m_mutex );
76cdf0e10cSrcweir for( DisposedCallerList::iterator ii = m_lst.begin() ;
77cdf0e10cSrcweir ii != m_lst.end() ;
78cdf0e10cSrcweir ++ ii )
79cdf0e10cSrcweir {
80cdf0e10cSrcweir if( (*ii) == nDisposeId )
81cdf0e10cSrcweir {
82cdf0e10cSrcweir m_lst.erase( ii );
83cdf0e10cSrcweir break;
84cdf0e10cSrcweir }
85cdf0e10cSrcweir }
86cdf0e10cSrcweir }
87cdf0e10cSrcweir
isDisposed(sal_Int64 nDisposeId)88cdf0e10cSrcweir sal_Bool DisposedCallerAdmin::isDisposed( sal_Int64 nDisposeId )
89cdf0e10cSrcweir {
90cdf0e10cSrcweir MutexGuard guard( m_mutex );
91cdf0e10cSrcweir for( DisposedCallerList::iterator ii = m_lst.begin() ;
92cdf0e10cSrcweir ii != m_lst.end() ;
93cdf0e10cSrcweir ++ ii )
94cdf0e10cSrcweir {
95cdf0e10cSrcweir if( (*ii) == nDisposeId )
96cdf0e10cSrcweir {
97cdf0e10cSrcweir return sal_True;
98cdf0e10cSrcweir }
99cdf0e10cSrcweir }
100cdf0e10cSrcweir return sal_False;
101cdf0e10cSrcweir }
102cdf0e10cSrcweir
103cdf0e10cSrcweir
104cdf0e10cSrcweir //-------------------------------------------------------------------------------
105cdf0e10cSrcweir
106cdf0e10cSrcweir struct theThreadPool :
107cdf0e10cSrcweir public rtl::StaticWithInit< ThreadPoolHolder, theThreadPool >
108cdf0e10cSrcweir {
operator ()cppu_threadpool::theThreadPool109cdf0e10cSrcweir ThreadPoolHolder operator () () {
110cdf0e10cSrcweir ThreadPoolHolder aRet(new ThreadPool());
111cdf0e10cSrcweir return aRet;
112cdf0e10cSrcweir }
113cdf0e10cSrcweir };
114cdf0e10cSrcweir
ThreadPool()115cdf0e10cSrcweir ThreadPool::ThreadPool()
116cdf0e10cSrcweir {
117cdf0e10cSrcweir m_DisposedCallerAdmin = DisposedCallerAdmin::getInstance();
118cdf0e10cSrcweir }
119cdf0e10cSrcweir
~ThreadPool()120cdf0e10cSrcweir ThreadPool::~ThreadPool()
121cdf0e10cSrcweir {
122cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1
123cdf0e10cSrcweir if( m_mapQueue.size() )
124cdf0e10cSrcweir {
125cdf0e10cSrcweir printf( "ThreadIdHashMap : %lu left\n" , static_cast<unsigned long>(m_mapQueue.size()) );
126cdf0e10cSrcweir }
127cdf0e10cSrcweir #endif
128cdf0e10cSrcweir }
getInstance()129cdf0e10cSrcweir ThreadPoolHolder ThreadPool::getInstance()
130cdf0e10cSrcweir {
131cdf0e10cSrcweir return theThreadPool::get();
132cdf0e10cSrcweir }
133cdf0e10cSrcweir
134cdf0e10cSrcweir
dispose(sal_Int64 nDisposeId)135cdf0e10cSrcweir void ThreadPool::dispose( sal_Int64 nDisposeId )
136cdf0e10cSrcweir {
137cdf0e10cSrcweir if( nDisposeId )
138cdf0e10cSrcweir {
139cdf0e10cSrcweir m_DisposedCallerAdmin->dispose( nDisposeId );
140cdf0e10cSrcweir
141cdf0e10cSrcweir MutexGuard guard( m_mutex );
142cdf0e10cSrcweir for( ThreadIdHashMap::iterator ii = m_mapQueue.begin() ;
143cdf0e10cSrcweir ii != m_mapQueue.end();
144cdf0e10cSrcweir ++ii)
145cdf0e10cSrcweir {
146cdf0e10cSrcweir if( (*ii).second.first )
147cdf0e10cSrcweir {
148cdf0e10cSrcweir (*ii).second.first->dispose( nDisposeId );
149cdf0e10cSrcweir }
150cdf0e10cSrcweir if( (*ii).second.second )
151cdf0e10cSrcweir {
152cdf0e10cSrcweir (*ii).second.second->dispose( nDisposeId );
153cdf0e10cSrcweir }
154cdf0e10cSrcweir }
155cdf0e10cSrcweir }
156cdf0e10cSrcweir else
157cdf0e10cSrcweir {
158cdf0e10cSrcweir {
159cdf0e10cSrcweir MutexGuard guard( m_mutexWaitingThreadList );
160cdf0e10cSrcweir for( WaitingThreadList::iterator ii = m_lstThreads.begin() ;
161cdf0e10cSrcweir ii != m_lstThreads.end() ;
162cdf0e10cSrcweir ++ ii )
163cdf0e10cSrcweir {
164cdf0e10cSrcweir // wake the threads up
165cdf0e10cSrcweir osl_setCondition( (*ii)->condition );
166cdf0e10cSrcweir }
167cdf0e10cSrcweir }
168cdf0e10cSrcweir ThreadAdmin::getInstance()->join();
169cdf0e10cSrcweir }
170cdf0e10cSrcweir }
171cdf0e10cSrcweir
stopDisposing(sal_Int64 nDisposeId)172cdf0e10cSrcweir void ThreadPool::stopDisposing( sal_Int64 nDisposeId )
173cdf0e10cSrcweir {
174cdf0e10cSrcweir m_DisposedCallerAdmin->stopDisposing( nDisposeId );
175cdf0e10cSrcweir }
176cdf0e10cSrcweir
177cdf0e10cSrcweir /******************
178cdf0e10cSrcweir * This methods lets the thread wait a certain amount of time. If within this timespan
179cdf0e10cSrcweir * a new request comes in, this thread is reused. This is done only to improve performance,
180cdf0e10cSrcweir * it is not required for threadpool functionality.
181cdf0e10cSrcweir ******************/
waitInPool(ORequestThread * pThread)182cdf0e10cSrcweir void ThreadPool::waitInPool( ORequestThread * pThread )
183cdf0e10cSrcweir {
184cdf0e10cSrcweir struct WaitingThread waitingThread;
185cdf0e10cSrcweir waitingThread.condition = osl_createCondition();
186cdf0e10cSrcweir waitingThread.thread = pThread;
187cdf0e10cSrcweir {
188cdf0e10cSrcweir MutexGuard guard( m_mutexWaitingThreadList );
189cdf0e10cSrcweir m_lstThreads.push_front( &waitingThread );
190cdf0e10cSrcweir }
191cdf0e10cSrcweir
192cdf0e10cSrcweir // let the thread wait 2 seconds
193cdf0e10cSrcweir TimeValue time = { 2 , 0 };
194cdf0e10cSrcweir osl_waitCondition( waitingThread.condition , &time );
195cdf0e10cSrcweir
196cdf0e10cSrcweir {
197cdf0e10cSrcweir MutexGuard guard ( m_mutexWaitingThreadList );
198cdf0e10cSrcweir if( waitingThread.thread )
199cdf0e10cSrcweir {
200cdf0e10cSrcweir // thread wasn't reused, remove it from the list
201cdf0e10cSrcweir WaitingThreadList::iterator ii = find(
202cdf0e10cSrcweir m_lstThreads.begin(), m_lstThreads.end(), &waitingThread );
203cdf0e10cSrcweir OSL_ASSERT( ii != m_lstThreads.end() );
204cdf0e10cSrcweir m_lstThreads.erase( ii );
205cdf0e10cSrcweir }
206cdf0e10cSrcweir }
207cdf0e10cSrcweir
208cdf0e10cSrcweir osl_destroyCondition( waitingThread.condition );
209cdf0e10cSrcweir }
210cdf0e10cSrcweir
createThread(JobQueue * pQueue,const ByteSequence & aThreadId,sal_Bool bAsynchron)211cdf0e10cSrcweir void ThreadPool::createThread( JobQueue *pQueue ,
212cdf0e10cSrcweir const ByteSequence &aThreadId,
213cdf0e10cSrcweir sal_Bool bAsynchron )
214cdf0e10cSrcweir {
215cdf0e10cSrcweir sal_Bool bCreate = sal_True;
216cdf0e10cSrcweir {
217cdf0e10cSrcweir // Can a thread be reused ?
218cdf0e10cSrcweir MutexGuard guard( m_mutexWaitingThreadList );
219cdf0e10cSrcweir if( ! m_lstThreads.empty() )
220cdf0e10cSrcweir {
221cdf0e10cSrcweir // inform the thread and let it go
222cdf0e10cSrcweir struct WaitingThread *pWaitingThread = m_lstThreads.back();
223cdf0e10cSrcweir pWaitingThread->thread->setTask( pQueue , aThreadId , bAsynchron );
224cdf0e10cSrcweir pWaitingThread->thread = 0;
225cdf0e10cSrcweir
226cdf0e10cSrcweir // remove from list
227cdf0e10cSrcweir m_lstThreads.pop_back();
228cdf0e10cSrcweir
229cdf0e10cSrcweir // let the thread go
230cdf0e10cSrcweir osl_setCondition( pWaitingThread->condition );
231cdf0e10cSrcweir bCreate = sal_False;
232cdf0e10cSrcweir }
233cdf0e10cSrcweir }
234cdf0e10cSrcweir
235cdf0e10cSrcweir if( bCreate )
236cdf0e10cSrcweir {
237cdf0e10cSrcweir ORequestThread *pThread =
238cdf0e10cSrcweir new ORequestThread( pQueue , aThreadId, bAsynchron);
239cdf0e10cSrcweir // deletes itself !
240cdf0e10cSrcweir pThread->create();
241cdf0e10cSrcweir }
242cdf0e10cSrcweir }
243cdf0e10cSrcweir
revokeQueue(const ByteSequence & aThreadId,sal_Bool bAsynchron)244cdf0e10cSrcweir sal_Bool ThreadPool::revokeQueue( const ByteSequence &aThreadId, sal_Bool bAsynchron )
245cdf0e10cSrcweir {
246cdf0e10cSrcweir MutexGuard guard( m_mutex );
247cdf0e10cSrcweir
248cdf0e10cSrcweir ThreadIdHashMap::iterator ii = m_mapQueue.find( aThreadId );
249cdf0e10cSrcweir OSL_ASSERT( ii != m_mapQueue.end() );
250cdf0e10cSrcweir
251cdf0e10cSrcweir if( bAsynchron )
252cdf0e10cSrcweir {
253cdf0e10cSrcweir if( ! (*ii).second.second->isEmpty() )
254cdf0e10cSrcweir {
255cdf0e10cSrcweir // another thread has put something into the queue
256cdf0e10cSrcweir return sal_False;
257cdf0e10cSrcweir }
258cdf0e10cSrcweir
259cdf0e10cSrcweir (*ii).second.second = 0;
260cdf0e10cSrcweir if( (*ii).second.first )
261cdf0e10cSrcweir {
262cdf0e10cSrcweir // all oneway request have been processed, now
263cdf0e10cSrcweir // synchronus requests may go on
264cdf0e10cSrcweir (*ii).second.first->resume();
265cdf0e10cSrcweir }
266cdf0e10cSrcweir }
267cdf0e10cSrcweir else
268cdf0e10cSrcweir {
269cdf0e10cSrcweir if( ! (*ii).second.first->isEmpty() )
270cdf0e10cSrcweir {
271cdf0e10cSrcweir // another thread has put something into the queue
272cdf0e10cSrcweir return sal_False;
273cdf0e10cSrcweir }
274cdf0e10cSrcweir (*ii).second.first = 0;
275cdf0e10cSrcweir }
276cdf0e10cSrcweir
277cdf0e10cSrcweir if( 0 == (*ii).second.first && 0 == (*ii).second.second )
278cdf0e10cSrcweir {
279cdf0e10cSrcweir m_mapQueue.erase( ii );
280cdf0e10cSrcweir }
281cdf0e10cSrcweir
282cdf0e10cSrcweir return sal_True;
283cdf0e10cSrcweir }
284cdf0e10cSrcweir
285cdf0e10cSrcweir
addJob(const ByteSequence & aThreadId,sal_Bool bAsynchron,void * pThreadSpecificData,RequestFun * doRequest)286cdf0e10cSrcweir void ThreadPool::addJob(
287cdf0e10cSrcweir const ByteSequence &aThreadId ,
288cdf0e10cSrcweir sal_Bool bAsynchron,
289cdf0e10cSrcweir void *pThreadSpecificData,
290cdf0e10cSrcweir RequestFun * doRequest )
291cdf0e10cSrcweir {
292cdf0e10cSrcweir sal_Bool bCreateThread = sal_False;
293cdf0e10cSrcweir JobQueue *pQueue = 0;
294cdf0e10cSrcweir {
295cdf0e10cSrcweir MutexGuard guard( m_mutex );
296cdf0e10cSrcweir
297cdf0e10cSrcweir ThreadIdHashMap::iterator ii = m_mapQueue.find( aThreadId );
298cdf0e10cSrcweir
299cdf0e10cSrcweir if( ii == m_mapQueue.end() )
300cdf0e10cSrcweir {
301cdf0e10cSrcweir m_mapQueue[ aThreadId ] = pair < JobQueue * , JobQueue * > ( 0 , 0 );
302cdf0e10cSrcweir ii = m_mapQueue.find( aThreadId );
303cdf0e10cSrcweir OSL_ASSERT( ii != m_mapQueue.end() );
304cdf0e10cSrcweir }
305cdf0e10cSrcweir
306cdf0e10cSrcweir if( bAsynchron )
307cdf0e10cSrcweir {
308cdf0e10cSrcweir if( ! (*ii).second.second )
309cdf0e10cSrcweir {
310cdf0e10cSrcweir (*ii).second.second = new JobQueue();
311cdf0e10cSrcweir bCreateThread = sal_True;
312cdf0e10cSrcweir }
313cdf0e10cSrcweir pQueue = (*ii).second.second;
314cdf0e10cSrcweir }
315cdf0e10cSrcweir else
316cdf0e10cSrcweir {
317cdf0e10cSrcweir if( ! (*ii).second.first )
318cdf0e10cSrcweir {
319cdf0e10cSrcweir (*ii).second.first = new JobQueue();
320cdf0e10cSrcweir bCreateThread = sal_True;
321cdf0e10cSrcweir }
322cdf0e10cSrcweir pQueue = (*ii).second.first;
323cdf0e10cSrcweir
324cdf0e10cSrcweir if( (*ii).second.second && ( (*ii).second.second->isBusy() ) )
325cdf0e10cSrcweir {
326cdf0e10cSrcweir pQueue->suspend();
327cdf0e10cSrcweir }
328cdf0e10cSrcweir }
329cdf0e10cSrcweir pQueue->add( pThreadSpecificData , doRequest );
330cdf0e10cSrcweir }
331cdf0e10cSrcweir
332cdf0e10cSrcweir if( bCreateThread )
333cdf0e10cSrcweir {
334cdf0e10cSrcweir createThread( pQueue , aThreadId , bAsynchron);
335cdf0e10cSrcweir }
336cdf0e10cSrcweir }
337cdf0e10cSrcweir
prepare(const ByteSequence & aThreadId)338cdf0e10cSrcweir void ThreadPool::prepare( const ByteSequence &aThreadId )
339cdf0e10cSrcweir {
340cdf0e10cSrcweir MutexGuard guard( m_mutex );
341cdf0e10cSrcweir
342cdf0e10cSrcweir ThreadIdHashMap::iterator ii = m_mapQueue.find( aThreadId );
343cdf0e10cSrcweir
344cdf0e10cSrcweir if( ii == m_mapQueue.end() )
345cdf0e10cSrcweir {
346cdf0e10cSrcweir JobQueue *p = new JobQueue();
347cdf0e10cSrcweir m_mapQueue[ aThreadId ] = pair< JobQueue * , JobQueue * > ( p , 0 );
348cdf0e10cSrcweir }
349cdf0e10cSrcweir else if( 0 == (*ii).second.first )
350cdf0e10cSrcweir {
351cdf0e10cSrcweir (*ii).second.first = new JobQueue();
352cdf0e10cSrcweir }
353cdf0e10cSrcweir }
354cdf0e10cSrcweir
enter(const ByteSequence & aThreadId,sal_Int64 nDisposeId)355cdf0e10cSrcweir void * ThreadPool::enter( const ByteSequence & aThreadId , sal_Int64 nDisposeId )
356cdf0e10cSrcweir {
357cdf0e10cSrcweir JobQueue *pQueue = 0;
358cdf0e10cSrcweir {
359cdf0e10cSrcweir MutexGuard guard( m_mutex );
360cdf0e10cSrcweir
361cdf0e10cSrcweir ThreadIdHashMap::iterator ii = m_mapQueue.find( aThreadId );
362cdf0e10cSrcweir
363cdf0e10cSrcweir OSL_ASSERT( ii != m_mapQueue.end() );
364cdf0e10cSrcweir pQueue = (*ii).second.first;
365cdf0e10cSrcweir }
366cdf0e10cSrcweir
367cdf0e10cSrcweir OSL_ASSERT( pQueue );
368cdf0e10cSrcweir void *pReturn = pQueue->enter( nDisposeId );
369cdf0e10cSrcweir
370cdf0e10cSrcweir if( pQueue->isCallstackEmpty() )
371cdf0e10cSrcweir {
372cdf0e10cSrcweir if( revokeQueue( aThreadId , sal_False) )
373cdf0e10cSrcweir {
374cdf0e10cSrcweir // remove queue
375cdf0e10cSrcweir delete pQueue;
376cdf0e10cSrcweir }
377cdf0e10cSrcweir }
378cdf0e10cSrcweir return pReturn;
379cdf0e10cSrcweir }
380cdf0e10cSrcweir }
381cdf0e10cSrcweir
382cdf0e10cSrcweir
383cdf0e10cSrcweir using namespace cppu_threadpool;
384cdf0e10cSrcweir
385cdf0e10cSrcweir struct uno_ThreadPool_Equal
386cdf0e10cSrcweir {
operator ()uno_ThreadPool_Equal387cdf0e10cSrcweir sal_Bool operator () ( const uno_ThreadPool &a , const uno_ThreadPool &b ) const
388cdf0e10cSrcweir {
389cdf0e10cSrcweir return a == b;
390cdf0e10cSrcweir }
391cdf0e10cSrcweir };
392cdf0e10cSrcweir
393cdf0e10cSrcweir struct uno_ThreadPool_Hash
394cdf0e10cSrcweir {
operator ()uno_ThreadPool_Hash395cdf0e10cSrcweir sal_Size operator () ( const uno_ThreadPool &a ) const
396cdf0e10cSrcweir {
397cdf0e10cSrcweir return (sal_Size) a;
398cdf0e10cSrcweir }
399cdf0e10cSrcweir };
400cdf0e10cSrcweir
401cdf0e10cSrcweir
402cdf0e10cSrcweir
403cdf0e10cSrcweir typedef ::std::hash_map< uno_ThreadPool, ThreadPoolHolder, uno_ThreadPool_Hash, uno_ThreadPool_Equal > ThreadpoolHashSet;
404cdf0e10cSrcweir
405cdf0e10cSrcweir static ThreadpoolHashSet *g_pThreadpoolHashSet;
406cdf0e10cSrcweir
407cdf0e10cSrcweir struct _uno_ThreadPool
408cdf0e10cSrcweir {
409cdf0e10cSrcweir sal_Int32 dummy;
410cdf0e10cSrcweir };
411cdf0e10cSrcweir
412cdf0e10cSrcweir extern "C" uno_ThreadPool SAL_CALL
uno_threadpool_create()413cdf0e10cSrcweir uno_threadpool_create() SAL_THROW_EXTERN_C()
414cdf0e10cSrcweir {
415cdf0e10cSrcweir MutexGuard guard( Mutex::getGlobalMutex() );
416cdf0e10cSrcweir if( ! g_pThreadpoolHashSet )
417cdf0e10cSrcweir {
418cdf0e10cSrcweir g_pThreadpoolHashSet = new ThreadpoolHashSet();
419cdf0e10cSrcweir }
420cdf0e10cSrcweir
421cdf0e10cSrcweir // Just ensure that the handle is unique in the process (via heap)
422cdf0e10cSrcweir uno_ThreadPool h = new struct _uno_ThreadPool;
423cdf0e10cSrcweir g_pThreadpoolHashSet->insert( ThreadpoolHashSet::value_type(h, ThreadPool::getInstance()) );
424cdf0e10cSrcweir return h;
425cdf0e10cSrcweir }
426cdf0e10cSrcweir
427cdf0e10cSrcweir extern "C" void SAL_CALL
uno_threadpool_attach(uno_ThreadPool)428cdf0e10cSrcweir uno_threadpool_attach( uno_ThreadPool ) SAL_THROW_EXTERN_C()
429cdf0e10cSrcweir {
430cdf0e10cSrcweir sal_Sequence *pThreadId = 0;
431cdf0e10cSrcweir uno_getIdOfCurrentThread( &pThreadId );
432cdf0e10cSrcweir ThreadPool::getInstance()->prepare( pThreadId );
433cdf0e10cSrcweir rtl_byte_sequence_release( pThreadId );
434cdf0e10cSrcweir uno_releaseIdFromCurrentThread();
435cdf0e10cSrcweir }
436cdf0e10cSrcweir
437cdf0e10cSrcweir extern "C" void SAL_CALL
uno_threadpool_enter(uno_ThreadPool hPool,void ** ppJob)438cdf0e10cSrcweir uno_threadpool_enter( uno_ThreadPool hPool , void **ppJob )
439cdf0e10cSrcweir SAL_THROW_EXTERN_C()
440cdf0e10cSrcweir {
441cdf0e10cSrcweir sal_Sequence *pThreadId = 0;
442cdf0e10cSrcweir uno_getIdOfCurrentThread( &pThreadId );
443cdf0e10cSrcweir *ppJob =
444cdf0e10cSrcweir ThreadPool::getInstance()->enter(
445cdf0e10cSrcweir pThreadId,
446cdf0e10cSrcweir sal::static_int_cast< sal_Int64 >(
447cdf0e10cSrcweir reinterpret_cast< sal_IntPtr >(hPool)) );
448cdf0e10cSrcweir rtl_byte_sequence_release( pThreadId );
449cdf0e10cSrcweir uno_releaseIdFromCurrentThread();
450cdf0e10cSrcweir }
451cdf0e10cSrcweir
452cdf0e10cSrcweir extern "C" void SAL_CALL
uno_threadpool_detach(uno_ThreadPool)453cdf0e10cSrcweir uno_threadpool_detach( uno_ThreadPool ) SAL_THROW_EXTERN_C()
454cdf0e10cSrcweir {
455cdf0e10cSrcweir // we might do here some tiding up in case a thread called attach but never detach
456cdf0e10cSrcweir }
457cdf0e10cSrcweir
458cdf0e10cSrcweir extern "C" void SAL_CALL
uno_threadpool_putJob(uno_ThreadPool,sal_Sequence * pThreadId,void * pJob,void (SAL_CALL * doRequest)(void * pThreadSpecificData),sal_Bool bIsOneway)459cdf0e10cSrcweir uno_threadpool_putJob(
460cdf0e10cSrcweir uno_ThreadPool,
461cdf0e10cSrcweir sal_Sequence *pThreadId,
462cdf0e10cSrcweir void *pJob,
463cdf0e10cSrcweir void ( SAL_CALL * doRequest ) ( void *pThreadSpecificData ),
464cdf0e10cSrcweir sal_Bool bIsOneway ) SAL_THROW_EXTERN_C()
465cdf0e10cSrcweir {
466cdf0e10cSrcweir ThreadPool::getInstance()->addJob( pThreadId, bIsOneway, pJob ,doRequest );
467cdf0e10cSrcweir }
468cdf0e10cSrcweir
469cdf0e10cSrcweir extern "C" void SAL_CALL
uno_threadpool_dispose(uno_ThreadPool hPool)470cdf0e10cSrcweir uno_threadpool_dispose( uno_ThreadPool hPool ) SAL_THROW_EXTERN_C()
471cdf0e10cSrcweir {
472cdf0e10cSrcweir ThreadPool::getInstance()->dispose(
473cdf0e10cSrcweir sal::static_int_cast< sal_Int64 >(
474cdf0e10cSrcweir reinterpret_cast< sal_IntPtr >(hPool)) );
475cdf0e10cSrcweir }
476cdf0e10cSrcweir
477cdf0e10cSrcweir extern "C" void SAL_CALL
uno_threadpool_destroy(uno_ThreadPool hPool)478cdf0e10cSrcweir uno_threadpool_destroy( uno_ThreadPool hPool ) SAL_THROW_EXTERN_C()
479cdf0e10cSrcweir {
480cdf0e10cSrcweir ThreadPool::getInstance()->stopDisposing(
481cdf0e10cSrcweir sal::static_int_cast< sal_Int64 >(
482cdf0e10cSrcweir reinterpret_cast< sal_IntPtr >(hPool)) );
483cdf0e10cSrcweir
484cdf0e10cSrcweir if( hPool )
485cdf0e10cSrcweir {
486cdf0e10cSrcweir // special treatment for 0 !
487cdf0e10cSrcweir OSL_ASSERT( g_pThreadpoolHashSet );
488cdf0e10cSrcweir
489cdf0e10cSrcweir MutexGuard guard( Mutex::getGlobalMutex() );
490cdf0e10cSrcweir
491cdf0e10cSrcweir ThreadpoolHashSet::iterator ii = g_pThreadpoolHashSet->find( hPool );
492cdf0e10cSrcweir OSL_ASSERT( ii != g_pThreadpoolHashSet->end() );
493cdf0e10cSrcweir g_pThreadpoolHashSet->erase( ii );
494cdf0e10cSrcweir delete hPool;
495cdf0e10cSrcweir
496cdf0e10cSrcweir if( g_pThreadpoolHashSet->empty() )
497cdf0e10cSrcweir {
498cdf0e10cSrcweir delete g_pThreadpoolHashSet;
499cdf0e10cSrcweir g_pThreadpoolHashSet = 0;
500cdf0e10cSrcweir }
501cdf0e10cSrcweir }
502cdf0e10cSrcweir }
503