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