changed: auto add updateData callback to stages so that stagedata can be updated...
[opensg.git] / Source / Base / Threading / OSGBaseThread.cpp
blob9afc62c3050089c177707b1ef6d0715465867903
1 /*---------------------------------------------------------------------------*\
2 * OpenSG *
3 * *
4 * *
5 * Copyright (C) 2000-2002 by the OpenSG Forum *
6 * *
7 * www.opensg.org *
8 * *
9 * contact: dirk@opensg.org, gerrit.voss@vossg.org, jbehr@zgdv.de *
10 * *
11 \*---------------------------------------------------------------------------*/
12 /*---------------------------------------------------------------------------*\
13 * License *
14 * *
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. *
18 * *
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. *
23 * *
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. *
27 * *
28 \*---------------------------------------------------------------------------*/
29 /*---------------------------------------------------------------------------*\
30 * Changes *
31 * *
32 * *
33 * *
34 * *
35 * *
36 * *
37 \*---------------------------------------------------------------------------*/
39 #include <cstdlib>
40 #include <cstdio>
42 #include "OSGConfig.h"
44 #include <iostream>
46 #include "OSGBaseThread.h"
47 #include "OSGBaseFunctions.h"
48 #include "OSGThreadManager.h"
49 #include "OSGLog.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>
55 #include <cerrno>
57 #include <sys/types.h>
58 #include <sys/wait.h>
59 #include <unistd.h>
60 #include <signal.h>
61 #endif
63 #if defined (OSG_USE_PTHREADS)
64 #include <signal.h>
65 #endif
67 OSG_USING_NAMESPACE
69 //---------------------------------------------------------------------------
70 // Class
71 //---------------------------------------------------------------------------
75 /*--------------------------- Constructors --------------------------------*/
77 BaseThreadCommonBase::BaseThreadCommonBase(const Char8 *szName,
78 UInt32 uiId,
79 bool bGlobal) :
81 Inherited (szName, bGlobal),
82 _uiThreadId (uiId ),
83 _bInitialized(false )
87 /*---------------------------- Destructor ---------------------------------*/
89 BaseThreadCommonBase::~BaseThreadCommonBase(void)
95 #if defined (OSG_USE_PTHREADS)
97 //---------------------------------------------------------------------------
98 // Class
99 //---------------------------------------------------------------------------
101 #if defined(OSG_PTHREAD_ELF_TLS)
102 __thread BaseThread *BasePThreadBase::_pLocalThread = NULL;
103 #else
104 pthread_key_t BasePThreadBase::_threadKey;
105 #endif
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();
119 # endif
120 return _pLocalThread;
121 #else
122 BaseThread **pThread;
124 pThread = static_cast<BaseThread **>(pthread_getspecific(_threadKey));
126 # ifdef OSG_ENABLE_AUTOINIT_THREADS
127 if(pThread == NULL)
129 BaseThreadRefPtr pT = dynamic_pointer_cast<BaseThread>(
130 ThreadManager::the()->getThread(NULL, true, "OSGThread"));
132 pT->doAutoInit();
134 pThread = static_cast<BaseThread **>(pthread_getspecific(_threadKey));
136 #endif
138 return *pThread;
139 #endif
142 /*-------------------------------------------------------------------------*/
143 /* Helper */
145 void *BasePThreadBase::threadFunc(void *pThreadArg)
147 void **pArgs = static_cast<void **>(pThreadArg);
149 if(pArgs != NULL)
151 if(pArgs[2] != NULL)
153 static_cast<BaseThread *>(pArgs[2])->init();
155 if(pArgs[0] != NULL)
157 ThreadFuncF fThreadFunc = ThreadFuncF(pArgs[0]);
159 fThreadFunc(pArgs[1]);
162 static_cast<BaseThread *>(pArgs[2])->shutdown();
166 return NULL;
169 #if !defined(OSG_PTHREAD_ELF_TLS)
170 void BasePThreadBase::freeThread(void *pThread)
172 BaseThread **pT = static_cast<BaseThread **>(pThread);
174 if(pT != NULL)
176 if(*pT != NULL)
177 OSG::subRef(*pT);
179 delete pT;
182 pthread_setspecific(_threadKey, NULL);
184 #endif
186 /*--------------------------- Constructors --------------------------------*/
188 BasePThreadBase::BasePThreadBase(const Char8 *szName,
189 UInt32 uiId,
190 bool bGlobal) :
191 Inherited (szName, uiId, bGlobal),
193 _pThreadDesc(NULL),
194 _pBlockCond (NULL),
195 _pBlockMutex(NULL)
197 _pThreadData[0] = NULL;
198 _pThreadData[1] = NULL;
199 _pThreadData[2] = NULL;
202 /*-------------------------------------------------------------------------*/
203 /* Destructor */
205 BasePThreadBase::~BasePThreadBase(void)
207 delete _pThreadDesc;
209 _pThreadDesc = NULL;
212 /*-------------------------------------------------------------------------*/
213 /* Construction */
215 void BasePThreadBase::setupThread(void)
217 #ifdef OSG_PTHREAD_ELF_TLS
218 _pLocalThread = static_cast<BaseThread *>(this);
219 #else
220 BaseThread **pThread = new BaseThread *;
222 *pThread = static_cast<BaseThread *>(this);
224 pthread_setspecific(_threadKey, static_cast<void *>(pThread));
225 #endif
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)
244 return;
246 setupThread ();
247 setupBlockCond ();
249 _bInitialized = true;
252 void BasePThreadBase::shutdown(void)
254 if(_bInitialized == false)
255 return;
257 pthread_cond_destroy (_pBlockCond);
258 pthread_mutex_destroy(_pBlockMutex);
260 delete _pBlockCond;
261 delete _pBlockMutex;
263 #if !defined(OSG_PTHREAD_ELF_TLS)
264 BaseThread **pThread;
266 pThread = static_cast<BaseThread **>(pthread_getspecific(_threadKey));
268 delete pThread;
270 pthread_setspecific(_threadKey, NULL);
271 #else
272 _pLocalThread = NULL;
273 #endif
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,
299 void *pThreadArg)
301 bool returnValue = true;
302 Int32 rc = 0;
304 _bInitialized = false;
306 if(fThreadFunc != NULL)
308 if(_pThreadDesc == NULL)
309 _pThreadDesc = new pthread_t;
311 pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &rc);
313 #if __GNUC__ < 4
314 _pThreadData[0] = (void *)(fThreadFunc);
315 #else
316 _pThreadData[0] = reinterpret_cast<void *>(fThreadFunc);
317 #endif
318 _pThreadData[1] = pThreadArg;
319 _pThreadData[2] = static_cast <void *>(this );
321 rc = pthread_create(_pThreadDesc,
322 NULL,
323 BasePThreadBase::threadFunc,
324 static_cast<void *>(&_pThreadData));
326 if(rc != 0)
328 SFATAL << "OSGPTB : pthread_create failed" << std::endl;
329 returnValue = false;
332 else
334 SFATAL << "OSGPTB : no thread function given";
335 returnValue = false;
338 return returnValue;
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 //---------------------------------------------------------------------------
356 // Class
357 //---------------------------------------------------------------------------
359 /*------------------------------ Helper -----------------------------------*/
361 void BaseSprocBase::threadFunc(void *pThreadArg)
363 void **pArgs = (void **) pThreadArg;
365 if(pArgs != NULL)
367 if(pArgs[2] != NULL)
369 ((BaseThread *) pArgs[2])->init();
371 ((BaseThread *) pArgs[2])->setPid();
373 if(pArgs[0] != NULL)
375 ThreadFuncF threadFuncF = (ThreadFuncF) pArgs[0];
377 threadFuncF(pArgs[1]);
383 /*--------------------------- Constructors --------------------------------*/
385 BaseSprocBase::BaseSprocBase(const Char8 *szName,
386 UInt32 uiId ) :
387 Inherited(szName, uiId),
389 _pid (NULL)
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)
407 return;
409 setCurrentInternal((BaseThread *) this);
411 _bInitialized = true;
414 void BaseSprocBase::shutdown(void)
416 _bInitialized = false;
419 void BaseSprocBase::setPid(void)
421 _pid = getpid();
424 void BaseSprocBase::setCurrentInternal(BaseThread *pThread)
426 ((ProcessData *) PRDA->usr_prda.fill)->_pThread = pThread;
430 /*------------------------------ Join -------------------------------------*/
432 void BaseSprocBase::join(BaseSprocBase *pThread)
434 if(pThread != NULL)
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,
443 void *pThreadArg)
445 bool returnValue = true;
446 Int32 rc = 0;
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);
458 if(rc == -1)
460 SFATAL << "OSGSPB : sproc thread failed. Reason: "
461 << strerror(errno) << std::endl;
462 returnValue = false;
465 else
467 SFATAL << "OSGSPB : no thread function given";
468 returnValue = false;
471 return returnValue;
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 //---------------------------------------------------------------------------
489 // Class
490 //---------------------------------------------------------------------------
492 #if defined(OSG_WIN32_ASPECT_USE_LOCALSTORAGE)
493 UInt32 BaseWinThreadBase::_threadKey = 0;
494 #else
495 __declspec (thread) BaseThread *BaseWinThreadBase::_pThreadLocal = NULL;
496 #endif
498 /*------------------------------ Helper -----------------------------------*/
500 void BaseWinThreadBase::threadFunc(void *pThreadArg)
502 void **pArgs = (void **) pThreadArg;
504 if(pArgs != NULL)
506 if(pArgs[2] != NULL)
508 ((BaseThread *) pArgs[2])->init();
510 ((BaseWinThreadBase *) pArgs[2])->setPid();
512 if(pArgs[0] != NULL)
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,
527 UInt32 uiId,
528 bool bGlobal) :
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
554 if(pThread == NULL)
556 BaseWinThreadBase *pT = dynamic_cast<BaseThread *>(
557 ThreadManager::the()->getThread(NULL, "OSGThread"));
559 pT->doAutoInit();
561 pThread = (BaseThread **) TlsGetValue(_threadKey);
563 #endif
565 return *pThread;
566 #else
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();
575 # endif
577 return _pThreadLocal;
578 #endif
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;
590 #else
591 return _pThreadLocal;
592 #endif
595 /*--------------------------- Construction --------------------------------*/
597 void BaseWinThreadBase::init(void)
599 if(_bInitialized == true)
600 return;
602 setupThread();
604 _bInitialized = true;
607 void BaseWinThreadBase::shutdown(void)
609 if(_bInitialized == false)
610 return;
612 // TODO delet key value
614 #ifdef OSG_WIN32_ASPECT_USE_LOCALSTORAGE
615 BaseThread **pThread = static_cast<BaseThread **>(TlsGetValue(_threadKey));
617 delete pThread;
619 TlsSetValue(_threadKey, NULL);
620 #else
621 _pThreadLocal = NULL;
622 #endif
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);
647 #else
648 _pThreadLocal = (BaseThread *) this;
649 #endif
652 void BaseWinThreadBase::doAutoInit(void)
656 /*------------------------------ Join -------------------------------------*/
658 void BaseWinThreadBase::join(BaseWinThreadBase *pThread)
660 if(pThread != NULL)
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,
669 void *pThreadArg)
671 bool returnValue = true;
672 Handle rc = 0;
673 DWord tmp;
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,
686 _pThreadData,
688 &tmp);
690 this->setExternalHandle(rc);
692 if(rc == NULL)
694 SFATAL << "OSGWTB : sproc thread failed. Reason: "
695 << strerror(errno) << std::endl;
696 returnValue = false;
699 else
701 SFATAL << "OSGWTB : no thread function given";
702 returnValue = false;
705 return returnValue;
708 /*------------------------------- Dump ------------------------------------*/
710 void BaseWinThreadBase::print(void)
712 fprintf(stderr, "OSGWinThreadBase -%s-%u-\n", _szName, _uiThreadId);
715 #endif /* OSG_USE_WINTHREADS */
720 //---------------------------------------------------------------------------
721 // Class
722 //---------------------------------------------------------------------------
724 MPThreadType BaseThread::_type("OSGBaseThread",
725 "OSGMPBase",
726 &BaseThread::create,
727 BaseThread::initThreading);
730 /*------------------------------- Dump ------------------------------------*/
732 void BaseThread::print(void)
734 Inherited::print();
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)
761 int rc;
763 rc = pthread_key_create(&(BaseThread::_threadKey),
764 BaseThread::freeThread);
766 FFASSERT((rc == 0), 1, ("Failed to create pthread thread key\n");)
767 #endif
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");)
774 #endif
777 void BaseThread::terminateThreading(void)
779 FINFO(("BaseThread::terminateThreading\n"));
781 #if defined(OSG_USE_PTHREADS) && !defined(OSG_PTHREAD_ELF_TLS)
782 int rc;
784 rc = pthread_key_delete(BaseThread::_threadKey);
786 FFASSERT((rc == 0), 1, ("Failed to destroy pthread thread key\n"););
787 #endif
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;
796 #endif
799 void BaseThread::runWorkProc(void *pThread)
801 if(pThread != NULL)
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)
818 shutdown();
820 _bGlobal = false;
822 ThreadManager::the()->remove(this);
824 if(this != ThreadManager::getAppThread())
825 terminate();
828 /*------------------------------- Workproc --------------------------------*/
830 void BaseThread::workProc(void)