1 /*---------------------------------------------------------------------------*\
5 * Copyright (C) 2000-2002 by the OpenSG Forum *
9 * contact: dirk@opensg.org, gerrit.voss@vossg.org, jbehr@zgdv.de *
11 \*---------------------------------------------------------------------------*/
12 /*---------------------------------------------------------------------------*\
15 * This library is free software; you can redistribute it and/or modify it *
16 * under the terms of the GNU Library General Public License as published *
17 * by the Free Software Foundation, version 2. *
19 * This library is distributed in the hope that it will be useful, but *
20 * WITHOUT ANY WARRANTY; without even the implied warranty of *
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
22 * Library General Public License for more details. *
24 * You should have received a copy of the GNU Library General Public *
25 * License along with this library; if not, write to the Free Software *
26 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
28 \*---------------------------------------------------------------------------*/
29 /*---------------------------------------------------------------------------*\
37 \*---------------------------------------------------------------------------*/
42 #include "OSGConfig.h"
46 #include "OSGBaseThread.h"
47 #include "OSGBaseFunctions.h"
48 #include "OSGThreadManager.h"
51 #if ! defined (OSG_USE_PTHREADS) && ! defined (OSG_USE_WINTHREADS)
52 #define _SGI_MP_SOURCE
53 #include <sys/types.h>
54 #include <sys/prctl.h>
57 #include <sys/types.h>
63 #if defined (OSG_USE_PTHREADS)
69 //---------------------------------------------------------------------------
71 //---------------------------------------------------------------------------
75 /*--------------------------- Constructors --------------------------------*/
77 BaseThreadCommonBase::BaseThreadCommonBase(const Char8
*szName
,
81 Inherited (szName
, bGlobal
),
87 /*---------------------------- Destructor ---------------------------------*/
89 BaseThreadCommonBase::~BaseThreadCommonBase(void)
95 #if defined (OSG_USE_PTHREADS)
97 //---------------------------------------------------------------------------
99 //---------------------------------------------------------------------------
101 #if defined(OSG_PTHREAD_ELF_TLS)
102 __thread BaseThread
*BasePThreadBase::_pLocalThread
= NULL
;
104 pthread_key_t
BasePThreadBase::_threadKey
;
108 BaseThread
*BasePThreadBase::getCurrent(void)
110 #ifdef OSG_PTHREAD_ELF_TLS
111 # ifdef OSG_ENABLE_AUTOINIT_THREADS
112 if(_pLocalThread
== NULL
)
114 BaseThreadRefPtr pThread
= dynamic_pointer_cast
<BaseThread
>(
115 ThreadManager::the()->getThread(NULL
, true, "OSGThread"));
117 pThread
->doAutoInit();
120 return _pLocalThread
;
122 BaseThread
**pThread
;
124 pThread
= static_cast<BaseThread
**>(pthread_getspecific(_threadKey
));
126 # ifdef OSG_ENABLE_AUTOINIT_THREADS
129 BaseThreadRefPtr pT
= dynamic_pointer_cast
<BaseThread
>(
130 ThreadManager::the()->getThread(NULL
, true, "OSGThread"));
134 pThread
= static_cast<BaseThread
**>(pthread_getspecific(_threadKey
));
142 /*-------------------------------------------------------------------------*/
145 void *BasePThreadBase::threadFunc(void *pThreadArg
)
147 void **pArgs
= static_cast<void **>(pThreadArg
);
153 static_cast<BaseThread
*>(pArgs
[2])->init();
157 ThreadFuncF fThreadFunc
= ThreadFuncF(pArgs
[0]);
159 fThreadFunc(pArgs
[1]);
162 static_cast<BaseThread
*>(pArgs
[2])->shutdown();
169 #if !defined(OSG_PTHREAD_ELF_TLS)
170 void BasePThreadBase::freeThread(void *pThread
)
172 BaseThread
**pT
= static_cast<BaseThread
**>(pThread
);
182 pthread_setspecific(_threadKey
, NULL
);
186 /*--------------------------- Constructors --------------------------------*/
188 BasePThreadBase::BasePThreadBase(const Char8
*szName
,
191 Inherited (szName
, uiId
, bGlobal
),
197 _pThreadData
[0] = NULL
;
198 _pThreadData
[1] = NULL
;
199 _pThreadData
[2] = NULL
;
202 /*-------------------------------------------------------------------------*/
205 BasePThreadBase::~BasePThreadBase(void)
212 /*-------------------------------------------------------------------------*/
215 void BasePThreadBase::setupThread(void)
217 #ifdef OSG_PTHREAD_ELF_TLS
218 _pLocalThread
= static_cast<BaseThread
*>(this);
220 BaseThread
**pThread
= new BaseThread
*;
222 *pThread
= static_cast<BaseThread
*>(this);
224 pthread_setspecific(_threadKey
, static_cast<void *>(pThread
));
228 void BasePThreadBase::setupBlockCond(void)
230 _pBlockCond
= new pthread_cond_t
;
231 _pBlockMutex
= new pthread_mutex_t
;
233 pthread_cond_init (_pBlockCond
, NULL
);
234 pthread_mutex_init(_pBlockMutex
, NULL
);
237 void BasePThreadBase::doAutoInit(void)
241 void BasePThreadBase::init(void)
243 if(_bInitialized
== true)
249 _bInitialized
= true;
252 void BasePThreadBase::shutdown(void)
254 if(_bInitialized
== false)
257 pthread_cond_destroy (_pBlockCond
);
258 pthread_mutex_destroy(_pBlockMutex
);
263 #if !defined(OSG_PTHREAD_ELF_TLS)
264 BaseThread
**pThread
;
266 pThread
= static_cast<BaseThread
**>(pthread_getspecific(_threadKey
));
270 pthread_setspecific(_threadKey
, NULL
);
272 _pLocalThread
= NULL
;
275 // TODO release key value, block cond
277 _bInitialized
= false;
280 /*------------------------------ Join -------------------------------------*/
282 void BasePThreadBase::join(BasePThreadBase
*pThread
)
284 if(pThread
!= NULL
&& pThread
->_pThreadDesc
!= NULL
)
286 pthread_join(*(pThread
->_pThreadDesc
), NULL
);
288 delete pThread
->_pThreadDesc
;
290 pThread
->_pThreadDesc
= NULL
;
294 /*------------------------------- Run -------------------------------------*/
296 // This workaround was brought to you by gcc 2.95.3
298 bool BasePThreadBase::runFunction(ThreadFuncF fThreadFunc
,
301 bool returnValue
= true;
304 _bInitialized
= false;
306 if(fThreadFunc
!= NULL
)
308 if(_pThreadDesc
== NULL
)
309 _pThreadDesc
= new pthread_t
;
311 pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS
, &rc
);
314 _pThreadData
[0] = (void *)(fThreadFunc
);
316 _pThreadData
[0] = reinterpret_cast<void *>(fThreadFunc
);
318 _pThreadData
[1] = pThreadArg
;
319 _pThreadData
[2] = static_cast <void *>(this );
321 rc
= pthread_create(_pThreadDesc
,
323 BasePThreadBase::threadFunc
,
324 static_cast<void *>(&_pThreadData
));
328 SFATAL
<< "OSGPTB : pthread_create failed" << std::endl
;
334 SFATAL
<< "OSGPTB : no thread function given";
341 /*------------------------------ Dump -------------------------------------*/
343 void BasePThreadBase::print(void)
345 fprintf(stderr
, "OSGPThreadBase -%s-%d-\n", _szName
, _uiThreadId
);
348 #endif /* OSG_USE_PTHREADS */
353 #if defined (OSG_USE_SPROC)
355 //---------------------------------------------------------------------------
357 //---------------------------------------------------------------------------
359 /*------------------------------ Helper -----------------------------------*/
361 void BaseSprocBase::threadFunc(void *pThreadArg
)
363 void **pArgs
= (void **) pThreadArg
;
369 ((BaseThread
*) pArgs
[2])->init();
371 ((BaseThread
*) pArgs
[2])->setPid();
375 ThreadFuncF threadFuncF
= (ThreadFuncF
) pArgs
[0];
377 threadFuncF(pArgs
[1]);
383 /*--------------------------- Constructors --------------------------------*/
385 BaseSprocBase::BaseSprocBase(const Char8
*szName
,
387 Inherited(szName
, uiId
),
391 _pThreadData
[0] = NULL
;
392 _pThreadData
[1] = NULL
;
393 _pThreadData
[2] = NULL
;
396 /*---------------------------- Destructor ---------------------------------*/
398 BaseSprocBase::~BaseSprocBase(void)
402 /*--------------------------- Construction --------------------------------*/
404 void BaseSprocBase::init(void)
406 if(_bInitialized
== true)
409 setCurrentInternal((BaseThread
*) this);
411 _bInitialized
= true;
414 void BaseSprocBase::shutdown(void)
416 _bInitialized
= false;
419 void BaseSprocBase::setPid(void)
424 void BaseSprocBase::setCurrentInternal(BaseThread
*pThread
)
426 ((ProcessData
*) PRDA
->usr_prda
.fill
)->_pThread
= pThread
;
430 /*------------------------------ Join -------------------------------------*/
432 void BaseSprocBase::join(BaseSprocBase
*pThread
)
435 waitpid(pThread
->_pid
, NULL
, 0);
438 /*------------------------------- Run -------------------------------------*/
440 // This workaround was brought to you by gcc 2.95.3
442 bool BaseSprocBase::runFunction(ThreadFuncF fThreadFunc
,
445 bool returnValue
= true;
448 _bInitialized
= false;
450 if(fThreadFunc
!= NULL
)
452 _pThreadData
[0] = (void *) fThreadFunc
;
453 _pThreadData
[1] = pThreadArg
;
454 _pThreadData
[2] = (void *) this;
456 rc
= sproc(BaseSprocBase::threadFunc
, PR_SALL
, (void *) _pThreadData
);
460 SFATAL
<< "OSGSPB : sproc thread failed. Reason: "
461 << strerror(errno
) << std::endl
;
467 SFATAL
<< "OSGSPB : no thread function given";
474 /*------------------------------- Dump ------------------------------------*/
476 void BaseSprocBase::print(void)
478 fprintf(stderr
, "OSGSprocBase -%s-%d-\n", _szName
, _uiThreadId
);
481 #endif /* OSG_USE_SPROC */
486 #if defined (OSG_USE_WINTHREADS)
488 //---------------------------------------------------------------------------
490 //---------------------------------------------------------------------------
492 #if defined(OSG_WIN32_ASPECT_USE_LOCALSTORAGE)
493 UInt32
BaseWinThreadBase::_threadKey
= 0;
495 __declspec (thread
) BaseThread
*BaseWinThreadBase::_pThreadLocal
= NULL
;
498 /*------------------------------ Helper -----------------------------------*/
500 void BaseWinThreadBase::threadFunc(void *pThreadArg
)
502 void **pArgs
= (void **) pThreadArg
;
508 ((BaseThread
*) pArgs
[2])->init();
510 ((BaseWinThreadBase
*) pArgs
[2])->setPid();
514 ThreadFuncF threadFuncF
= (ThreadFuncF
) pArgs
[0];
516 threadFuncF(pArgs
[1]);
519 static_cast<BaseThread
*>(pArgs
[2])->shutdown();
524 /*--------------------------- Constructors --------------------------------*/
526 BaseWinThreadBase::BaseWinThreadBase(const Char8
*szName
,
529 Inherited (szName
, uiId
, bGlobal
),
531 _pThreadHandle (NULL
),
532 _pExternalHandle (NULL
),
533 _uiNativeThreadId(0 )
535 _pThreadData
[0] = NULL
;
536 _pThreadData
[1] = NULL
;
537 _pThreadData
[2] = NULL
;
540 /*---------------------------- Destructor ---------------------------------*/
542 BaseWinThreadBase::~BaseWinThreadBase(void)
546 BaseThread
*BaseWinThreadBase::getCurrent(void)
548 #ifdef OSG_WIN32_ASPECT_USE_LOCALSTORAGE
549 BaseThread
**pThread
;
551 pThread
= static_cast<BaseThread
**>(TlsGetValue(_threadKey
));
553 # ifdef OSG_ENABLE_AUTOINIT_THREADS
556 BaseWinThreadBase
*pT
= dynamic_cast<BaseThread
*>(
557 ThreadManager::the()->getThread(NULL
, "OSGThread"));
561 pThread
= (BaseThread
**) TlsGetValue(_threadKey
);
567 # ifdef OSG_ENABLE_AUTOINIT_THREADS
568 if(_pThreadLocal
== NULL
)
570 BaseWinThreadBase
*pThread
= dynamic_cast<BaseThread
*>(
571 ThreadManager::the()->getThread(NULL
, "OSGThread"));
573 pThread
->doAutoInit();
577 return _pThreadLocal
;
582 BaseThread
*BaseWinThreadBase::getCurrentInternal(void)
584 #ifdef OSG_WIN32_ASPECT_USE_LOCALSTORAGE
585 BaseThread
**pThread
;
587 pThread
= static_cast<BaseThread
**>(TlsGetValue(_threadKey
));
589 return (pThread
!= NULL
) ? *pThread
: NULL
;
591 return _pThreadLocal
;
595 /*--------------------------- Construction --------------------------------*/
597 void BaseWinThreadBase::init(void)
599 if(_bInitialized
== true)
604 _bInitialized
= true;
607 void BaseWinThreadBase::shutdown(void)
609 if(_bInitialized
== false)
612 // TODO delet key value
614 #ifdef OSG_WIN32_ASPECT_USE_LOCALSTORAGE
615 BaseThread
**pThread
= static_cast<BaseThread
**>(TlsGetValue(_threadKey
));
619 TlsSetValue(_threadKey
, NULL
);
621 _pThreadLocal
= NULL
;
624 _bInitialized
= false;
627 void BaseWinThreadBase::setPid(void)
629 _pThreadHandle
= GetCurrentThread ();
630 _uiNativeThreadId
= GetCurrentThreadId();
633 void BaseWinThreadBase::setExternalHandle(Handle pExternalHandle
)
635 _pExternalHandle
= pExternalHandle
;
639 void BaseWinThreadBase::setupThread(void)
641 #if defined (OSG_WIN32_ASPECT_USE_LOCALSTORAGE)
642 BaseThread
**pThread
= new BaseThread
*;
644 *pThread
= (BaseThread
*) this;
646 TlsSetValue(_threadKey
, pThread
);
648 _pThreadLocal
= (BaseThread
*) this;
652 void BaseWinThreadBase::doAutoInit(void)
656 /*------------------------------ Join -------------------------------------*/
658 void BaseWinThreadBase::join(BaseWinThreadBase
*pThread
)
661 WaitForSingleObject(pThread
->_pExternalHandle
, INFINITE
);
664 /*------------------------------- Run -------------------------------------*/
666 // This workaround was brought to you by gcc 2.95.3
668 bool BaseWinThreadBase::runFunction(ThreadFuncF fThreadFunc
,
671 bool returnValue
= true;
675 _bInitialized
= false;
677 if(fThreadFunc
!= NULL
)
679 _pThreadData
[0] = (void *) fThreadFunc
;
680 _pThreadData
[1] = pThreadArg
;
681 _pThreadData
[2] = (void *) this;
683 rc
= CreateThread(NULL
,
685 (LPTHREAD_START_ROUTINE
) BaseThreadBase::threadFunc
,
690 this->setExternalHandle(rc
);
694 SFATAL
<< "OSGWTB : sproc thread failed. Reason: "
695 << strerror(errno
) << std::endl
;
701 SFATAL
<< "OSGWTB : no thread function given";
708 /*------------------------------- Dump ------------------------------------*/
710 void BaseWinThreadBase::print(void)
712 fprintf(stderr
, "OSGWinThreadBase -%s-%u-\n", _szName
, _uiThreadId
);
715 #endif /* OSG_USE_WINTHREADS */
720 //---------------------------------------------------------------------------
722 //---------------------------------------------------------------------------
724 MPThreadType
BaseThread::_type("OSGBaseThread",
727 BaseThread::initThreading
);
730 /*------------------------------- Dump ------------------------------------*/
732 void BaseThread::print(void)
737 /*------------------------------- Get -------------------------------------*/
739 BaseThread::ObjTransitPtr
BaseThread::get(const Char8
*szName
, bool bGlobal
)
741 return ThreadManager::the()->getThread(szName
, bGlobal
, "OSGBaseThread");
744 BaseThread
*BaseThread::find(const Char8
*szName
)
746 return ThreadManager::the()->findThread(szName
);
749 /*------------------------------ Helper -----------------------------------*/
751 BaseThread
*BaseThread::create(const Char8
*szName
, UInt32 uiId
, bool bGlobal
)
753 return new BaseThread(szName
, uiId
, bGlobal
);
756 void BaseThread::initThreading(void)
758 FINFO(("BaseThread::initThreading\n"))
760 #if defined(OSG_USE_PTHREADS) && !defined(OSG_PTHREAD_ELF_TLS)
763 rc
= pthread_key_create(&(BaseThread::_threadKey
),
764 BaseThread::freeThread
);
766 FFASSERT((rc
== 0), 1, ("Failed to create pthread thread key\n");)
769 #if defined(OSG_USE_WINTHREADS) && defined(OSG_WIN32_ASPECT_USE_LOCALSTORAGE)
770 BaseThread::_threadKey
= TlsAlloc();
772 FFASSERT((BaseThread::_threadKey
!= 0xFFFFFFFF), 1,
773 ("Failed to alloc thread key local storage\n");)
777 void BaseThread::terminateThreading(void)
779 FINFO(("BaseThread::terminateThreading\n"));
781 #if defined(OSG_USE_PTHREADS) && !defined(OSG_PTHREAD_ELF_TLS)
784 rc
= pthread_key_delete(BaseThread::_threadKey
);
786 FFASSERT((rc
== 0), 1, ("Failed to destroy pthread thread key\n"););
789 #if defined(OSG_USE_WINTHREADS) && defined (OSG_WIN32_ASPECT_USE_LOCALSTORAGE)
790 if(BaseThread::_threadKey
!= 0xFFFFFFFF)
792 TlsFree(BaseThread::_threadKey
);
794 BaseThread::_threadKey
= 0xFFFFFFFF;
799 void BaseThread::runWorkProc(void *pThread
)
803 static_cast<BaseThread
*>(pThread
)->workProc();
807 /*--------------------------- Constructors --------------------------------*/
809 BaseThread::BaseThread(const Char8
*szName
, UInt32 uiId
, bool bGlobal
) :
810 Inherited(szName
, uiId
, bGlobal
)
814 /*---------------------------- Destructor ---------------------------------*/
816 BaseThread::~BaseThread(void)
822 ThreadManager::the()->remove(this);
824 if(this != ThreadManager::getAppThread())
828 /*------------------------------- Workproc --------------------------------*/
830 void BaseThread::workProc(void)