/* * Thread beginning */ static void *ProxyFunc( void *arg ) { CPThread *parent = (CPThread*)arg; // Set this thread's thread specific storage to IThread instance pointer if(pthread_setspecific(threadSpecificKey, parent) != 0) throw EThread("cannot set thread ptr in thread specific storage."); // Allow to terminate the thread without cancellation point pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, 0); // Run the code of the thread parent->Runnable->run(); { pthread_t thread_self = pthread_self(); // Make sure the parent still cares // If this thread was replaced with a new thread (which should not happen), // and the IThread object has been deleted, this will likely crash. if (parent->_ThreadHandle == thread_self) parent->_State = CPThread::ThreadStateFinished; else throw EThread("Thread ended after being detached, this should not happen"); } // Allow some clean // pthread_exit(0); return NULL; }
CPMainThread() : CPThread(NULL, 0) { if(pthread_key_create(&threadSpecificKey, NULL) != 0) throw EThread("cannot create thread specific storage key."); if(pthread_setspecific(threadSpecificKey, this) != 0) throw EThread("cannot set main thread ptr in thread specific storage."); }
void CWinThread::start () { if (isRunning()) throw EThread("Starting a thread that is already started, existing thread will continue running, this should not happen"); // ThreadHandle = (void *) ::CreateThread (NULL, _StackSize, ProxyFunc, this, 0, (DWORD *)&ThreadId); ThreadHandle = (void *) ::CreateThread (NULL, 0, ProxyFunc, this, 0, (DWORD *)&ThreadId); // nldebug("NLMISC: thread %x started for runnable '%x'", typeid( Runnable ).name()); // OutputDebugString(toString(NL_LOC_MSG " NLMISC: thread %x started for runnable '%s'\n", ThreadId, typeid( *Runnable ).name()).c_str()); SetThreadPriorityBoost (ThreadHandle, TRUE); // FALSE == Enable Priority Boost if (ThreadHandle == NULL) { throw EThread ( "Cannot create new thread" ); } _SuspendCount = 0; }
/* * start */ void CPThread::start() { pthread_attr_t tattr; int ret; if (_StackSize != 0) { /* initialized with default attributes */ ret = pthread_attr_init(&tattr); /* setting the size of the stack also */ ret = pthread_attr_setstacksize(&tattr, _StackSize); } bool detach_old_thread = false; pthread_t old_thread_handle; if (_State != ThreadStateNone) { if (_State == ThreadStateRunning) { // I don't know if this behaviour is allowed, but neither thread implementations // check the start function, and both simply let the existing running thread for what it is... // From now on, this is not allowed. throw EThread("Starting a thread that is already started, existing thread will continue running, this should not happen"); } detach_old_thread = true; old_thread_handle = _ThreadHandle; } if (pthread_create(&_ThreadHandle, _StackSize != 0 ? &tattr : NULL, ProxyFunc, this) != 0) { throw EThread("Cannot start new thread"); } _State = ThreadStateRunning; if (detach_old_thread) { // Docs don't say anything about what happens when pthread_create is called with existing handle referenced. if (old_thread_handle == _ThreadHandle) throw EThread("Thread handle did not change, this should not happen"); // Don't care about old thread, free resources when it terminates. pthread_detach(old_thread_handle); } }
/* * wait */ void CPThread::wait () { if(_State == 1) { if(pthread_join(_ThreadHandle, 0) != 0) { throw EThread( "Cannot join with thread" ); } _State = 2; // set to finished } }
/* * wait */ void CPThread::wait () { if (_State == ThreadStateRunning) { int error = pthread_join(_ThreadHandle, 0); switch (error) { case 0: break; case EINVAL: throw EThread("Thread is not joinable"); case ESRCH: throw EThread("No thread found with this id"); case EDEADLK: throw EThread("Deadlock detected or calling thread waits for itself"); default: throw EThread("Unknown thread join error"); } if(_State != ThreadStateFinished) throw EThread("Thread did not finish, this should not happen"); } }
/* * start */ void CPThread::start() { pthread_attr_t tattr; pthread_t tid; int ret; /* initialized with default attributes */ ret = pthread_attr_init(&tattr); /* setting the size of the stack also */ ret = pthread_attr_setstacksize(&tattr, _StackSize); if(pthread_create(&_ThreadHandle, _StackSize != 0 ? &tattr : 0, ProxyFunc, this) != 0) { throw EThread("Cannot start new thread"); } _State = 1; }
~CPMainThread() { if(pthread_key_delete(threadSpecificKey) != 0) throw EThread("cannot delete thread specific storage key."); }