📄 thread.cpp
字号:
pthread_attr_setdetachstate(&priv->_attr, PTHREAD_CREATE_JOINABLE);#ifdef PTHREAD_STACK_MIN if(stack && stack <= _autostack) pthread_attr_setstacksize(&priv->_attr, _autostack); else if(stack > _autostack) { if(stack < PTHREAD_STACK_MIN) stack = PTHREAD_STACK_MIN; else // align to nearest min boundry { salign = stack / PTHREAD_STACK_MIN; if(stack % PTHREAD_STACK_MIN) ++salign; stack = salign * PTHREAD_STACK_MIN; } if(stack && pthread_attr_setstacksize(&priv->_attr, stack)) {#ifdef CCXX_EXCEPTIONS switch(Thread::getException()) { case throwObject: throw(this); return;#ifdef COMMON_STD_EXCEPTION case throwException: throw(ThrException("no stack space")); return;#endif default: return; }#else return;#endif } }#endif#ifndef __FreeBSD__#ifdef _POSIX_THREAD_PRIORITY_SCHEDULING#ifdef HAVE_SCHED_GETSCHEDULER#define __HAS_PRIORITY_SCHEDULING__ if(pri) { struct sched_param sched; int policy; policy = sched_getscheduler(0); if(policy < 0) {#ifdef CCXX_EXCEPTIONS switch(Thread::getException()) { case throwObject: throw(this); return;#ifdef COMMON_STD_EXCEPTION case throwException: throw(ThrException("invalid scheduler")); return;#endif default: return; }#else return;#endif } sched_getparam(0, &sched); pri = sched.sched_priority - pri; if(pri > sched_get_priority_max(policy)) pri = sched_get_priority_max(policy); if(pri < sched_get_priority_min(policy)) pri = sched_get_priority_min(policy); sched.sched_priority = pri; pthread_attr_setschedpolicy(&priv->_attr, policy); pthread_attr_setschedparam(&priv->_attr, &sched); } #endif // ifdef HAVE_SCHED_GETSCHEDULER#endif // ifdef _POSIX_THREAD_PRIORITY_SCHEDULING#endif // ifndef __FreeBSD__#ifdef __HAS_PRIORITY_SCHEDULING__ if(!pri) pthread_attr_setinheritsched(&priv->_attr, PTHREAD_INHERIT_SCHED); #else pthread_attr_setinheritsched(&priv->_attr, PTHREAD_INHERIT_SCHED); #endif _parent = getThread(); priv->_throw = _parent->priv->_throw; _cancel = cancelInitial;#endif // WIN32}#ifndef WIN32Thread::Thread(const Thread &th){ priv = new ThreadImpl(threadTypeNormal); _parent = th._parent; priv->_attr = th.priv->_attr; _cancel = cancelInitial; _start = NULL; priv->_throw = th.priv->_throw; priv->_suspendEnable = false; setName(NULL); // sigset_t mask, newmask;// int rc;//// pthread_sigmask(SIG_BLOCK, blocked_signals(&newmask), &mask);// rc = pthread_create(&_tid, &_attr, exec_t(&ccxx_exec_handler), this);// pthread_sigmask(SIG_SETMASK, &mask, NULL);// if(rc && Thread::getException() == throwObject)// throw(this);//#ifdef COMMON_STD_EXCEPTION// else if(rc && Thread::getException() == throwException)// throw(ThrException("cannot start copy"));//#endif}#endif // ndef WIN32Thread::~Thread(){ if(!priv) return;#ifndef WIN32 if(this == &_mainthread) return;#endif if(priv->_type == threadTypeDummy) { delete priv; priv = NULL; return; } terminate();}void Thread::setName(const char *text){ if(text) snprintf(_name, sizeof(_name), "%s", text); else snprintf(_name, sizeof(_name), "%ld", (long)getId());} void Thread::initial(void){}void Thread::final(void){}void *Thread::getExtended(void){ return NULL;}void Thread::notify(Thread *){}bool Thread::isThread(void){ if(!priv) return false;#ifdef WIN32 return ((priv->_tid == GetCurrentThreadId())) ? true : false;#else return (priv->_tid == pthread_self()) ? true : false;#endif}bool Thread::isDetached(void){ if(!priv) return false;#ifdef WIN32 // win32 doesn't support detached threads directly return priv->_detached;#else int state; pthread_attr_getdetachstate(&priv->_attr, &state); if(state == PTHREAD_CREATE_DETACHED) return true; return false;#endif}cctid_t Thread::getId(void) const{ return priv->_tid;}bool Thread::isRunning(void){ if(!priv) return false;#ifdef WIN32 return (priv->_tid != 0 && priv->_active) ? true : false;#else return (priv->_tid != 0) ? true : false;#endif // WIN32}int Thread::start(Semaphore *st){ if(!priv) return -1;#ifdef WIN32 if(priv->_active) return -1; _start = st; priv->_hThread = (HANDLE)_beginthreadex(NULL, (unsigned)priv->_stack, (exec_t)&Execute, (void *)this, CREATE_SUSPENDED, (unsigned *)&priv->_tid); if(!priv->_hThread) { CloseHandle(priv->_cancellation); priv->_cancellation = NULL; return -1; } setCancel(cancelInitial); SetThreadPriority(priv->_hThread, priv->_priority); ResumeThread(priv->_hThread); priv->_active = true; return 0;#else if(priv->_tid) { if(_start) { _start->post(); return 0; } else return -1; } _start = st; return pthread_create(&priv->_tid, &priv->_attr, exec_t(&ccxx_exec_handler), this);#endif}int Thread::detach(Semaphore *st){ _parent = NULL;#ifdef WIN32 // win32 we emulate detach if(!priv) return -1; priv->_detached = true; if(!priv->_active) return Thread::start(st); else if(_start) _start->post(); return 0;#else int rtn; if(!priv) return -1; if(priv->_tid) { pthread_detach(priv->_tid); if(_start) { _start->post(); pthread_attr_setdetachstate(&priv->_attr, PTHREAD_CREATE_DETACHED); return 0; } return -1; } pthread_attr_setdetachstate(&priv->_attr, PTHREAD_CREATE_DETACHED); _start = st; rtn = pthread_create(&priv->_tid, &priv->_attr, exec_t(&ccxx_exec_handler), this); if(!rtn && priv->_tid) return 0; return -1;#endif}void Thread::terminate(void){#ifdef WIN32 HANDLE hThread; if(!priv) return; hThread = priv->_hThread; if (!priv->_tid || isThread()) { if( priv->_cancellation) ::CloseHandle(priv->_cancellation); if(hThread) ::CloseHandle(hThread); delete priv; priv = NULL; return; } bool terminated = false; if(!priv->_active && hThread != NULL) { // NOTE: add a test in testthread for multiple // suspended Terminate ResumeThread(hThread); TerminateThread(hThread, 0); terminated = true; } else if(hThread != NULL) { switch(_cancel) { case cancelImmediate: TerminateThread(hThread, 0); terminated = true; break; default: SetEvent(priv->_cancellation); } } if(hThread != NULL) { WaitForSingleObject(hThread, INFINITE); CloseHandle(hThread); hThread = NULL; }// what if parent already exited?// if(_parent)// _parent->notify(this); if(priv->_cancellation != NULL) CloseHandle(priv->_cancellation); priv->_cancellation = NULL; priv->_tid = 0; if(getThread() == this) _self.setKey(DUMMY_INVALID_THREAD); if (terminated) final();#else if(!priv) return; cctid_t jtid = priv->_jtid, tid = priv->_tid; if(jtid && (pthread_self() != jtid)) { pthread_join(jtid, NULL); priv->_jtid = 0; } else if((pthread_self() != tid) && tid) { // in suspend thread cannot be cancelled or signaled // ??? rigth // ccxx_resume(priv->_tid); // assure thread has ran before we try to cancel... if(_start) _start->post(); pthread_cancel(tid); if(!isDetached()) { pthread_join(tid,NULL); priv->_tid = 0; } } pthread_attr_destroy(&priv->_attr);#endif delete priv; priv = NULL;}void Thread::sync(void){#if defined(__MACH__) || defined(__GNU__) Thread::exit();#else Thread::sleep(TIMEOUT_INF);#endif}void Thread::exit(void){ if (isThread()) { setCancel(cancelDisabled);#ifdef WIN32 close(); ExitThread(0);#else pthread_exit(NULL);#endif // WIN32 } } void Thread::close(){ bool detached = isDetached();#if !defined(CCXX_SIG_THREAD_ALARM) && !defined(__CYGWIN32__) && !defined(__MINGW32__) && !defined(WIN32) if(this == PosixThread::_timer) PosixThread::_arm.leaveMutex();#endif setCancel(cancelDisabled);// if(_parent)// _parent->notify(this); // final can call destructor (that call Terminate) final(); // test if this class is self-exiting thread#ifdef WIN32 if (_self.getKey() == this)#else if (ThreadImpl::_self.getKey() == this)#endif { if(priv) {#ifndef WIN32 priv->_jtid = priv->_tid;#else priv->_active = false;#endif } joinSem.post(); } // see if detached, and hence self deleting if(detached) delete this;}#ifndef WIN32inline void ThreadImpl::ThreadCleanup(Thread* th){ // close thread // (freddy77) Originally I thougth to throw an exception for deferred // for capture it and cleanup using C++ destructor // this doesn't work out!! // Throwing exception here (in cleanup) core dump app th->close();}static void ccxx_thread_cleanup(void* arg){ ThreadImpl::ThreadCleanup( (Thread*)arg );}inline void ThreadImpl::ThreadExecHandler(Thread *th){ ThreadImpl::_self.setKey(th); sigset_t mask; pthread_sigmask(SIG_BLOCK, blocked_signals(&mask), NULL); th->priv->_tid = pthread_self();#if defined(HAVE_PTHREAD_MACH_THREAD_NP) th->priv->_mach = pthread_mach_thread_np(th->priv->_tid);#elif defined(_THR_MACH) th->priv->_mach = mach_thread_self();#endif th->setCancel(Thread::cancelInitial); // using SIGUSR3 do not enable suspend by default th->setSuspend(Thread::suspendEnable); th->yield(); if(th->_start) { th->_start->wait(); th->_start = NULL; } pthread_cleanup_push(ccxx_thread_cleanup,th); th->initial(); if(th->getCancel() == Thread::cancelInitial) th->setCancel(Thread::cancelDefault); th->run(); th->setCancel(Thread::cancelDisabled); pthread_cleanup_pop(0); if(th->isDetached()) ThreadImpl::_self.setKey(NULL); th->close(); pthread_exit(NULL);}// delete Thread class created for no CommonC++ threadinline void ThreadImpl::ThreadDestructor(Thread* th){ if (!th || th == DUMMY_INVALID_THREAD || !th->priv) return; if(!th->priv) return; if (th->priv->_type == threadTypeDummy) delete th;}static void ccxx_thread_destructor(void* arg){ ThreadImpl::ThreadDestructor( (Thread*)arg );}static void ccxx_exec_handler(Thread *th){ ThreadImpl::ThreadExecHandler(th);}#endif // ndef WIN32#ifdef CCXX_SIG_THREAD_CANCELvoid Thread::setCancel(Cancel mode){ sigset_t mask; sigemptyset(&mask); sigaddset(&mask, CCXX_SIG_THREAD_CANCEL); switch(mode) { case cancelImmediate: pthread_sigmask(SIG_UNBLOCK, &mask, NULL); break; case cancelInitial: case cancelDisabled: case cancelDeferred: pthread_sigmask(SIG_BLOCK, &mask, NULL); break; } _cancel = mode;}#elsevoid Thread::setCancel(Cancel mode){#ifdef WIN32 switch(mode) { case cancelDeferred: case cancelImmediate: _cancel = mode; yield(); break; case cancelDisabled: case cancelInitial: _cancel = mode; }#else int old; switch(mode) { case cancelImmediate: pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &old); pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &old); break; case cancelDeferred: pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &old); pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, &old); break; case cancelInitial: case cancelDisabled: pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &old); break; default: return; } _cancel = mode;#endif // WIN32}#endifvoid Thread::yield(void)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -