⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 wy_thread.cpp

📁 一个不错
💻 CPP
📖 第 1 页 / 共 2 页
字号:
  if((v=::pthread_attr_destroy(&_thrd_attr))!=0) {    // manu says only EINVAL could happen    WY_THROW( WyRet(v) );  }  if((v=::pthread_attr_init(&_thrd_attr))!=0) {    //    // manu says only ENOMEM, linux man just says errno.    //     ::pthread_attr_destroy(&_thrd_attr); // make this member invalid (release)    WY_THROW( WyRet(v) );  }  if((v=::pthread_attr_setdetachstate(&_thrd_attr,PTHREAD_CREATE_DETACHED))!=0) {    // man. indicates only EINVAL    WY_THROW( WyRet(v) );  }  this->_reset_avars();  _thrd_stat_cond.broadcast();  return(Ok);}catch(const WyRet& e) {#ifdef WY_DEBUG Wy::cerr << Wy::wrd(e) << '\n';#endif WY_THROW( WyRet(e) );}catch(const std::exception&) {#ifdef WY_DEBUG Wy::cerr << "std::exception\n";#endif WY_THROW( WyRet() );};// [Non-cancellation Point]void Wy_Thread::tmain_close(void) WY__TSPC(){ _non_cancellable(); WyLock aa(_mtx); WyRet r; // Detect earily (in case default _thrd_id is meaningful to pthread) // if(_thrd_id==Wy_ThreadID::Default_ThreadID) {   return; } if(::pthread_equal(_thrd_id,::pthread_self())) {   return; // thread can not cancel itself }  this->_cleanup_thread(aa);};// [Non-cancellation Point]//// [Syn] The final function of the thread tmain()//       _exit_obj is reset from ecode, and return pointer to _exit_obj////  Note: This member locks wy__toltab_ptr->mutex() and this->_mtx//void* Wy_Thread::_tmain_finish(const WyRet& ecode) WY__TSPC()try {  // thread cancelability disabled,  no need to recover, as going to end.  // _non_cancellable(); WyLock aa_toltab( wy__toltab_ptr->mutex() );   // lock toltab first WyLock aa_this(_mtx); _exit_obj=ecode; // Set the thread state to Stopped and boradcast, ref. note8 //  (destructor and reset() may wait on this) // _thrd_stat=Stopped; _thrd_stat_cond.broadcast(); // Decrease the number of total active(running) threads // if(wy__toltab_ptr->remove(Wy_ThreadID(_thrd_id))==false) {   WY_TERMINATE(""); } #ifdef WY_DEBUG {   WyLock atmp(wy_act_mutex);   ++wy_joined_cnt; } #endif return(&_exit_obj);}catch(const WyLock::Reply& e) { Wy__Base::put_abnmsg( e->c_repstr() ,__FILE__,__LINE__); Wy__Base::terminate();}catch(const WyRet& e) { Wy__Base::put_abnmsg( e->c_repstr() ,__FILE__,__LINE__); Wy__Base::terminate();}catch(const std::bad_alloc&) {  WY_TERMINATE(""); // so we can trace the line}catch(const std::exception&) {  WY_TERMINATE(""); // so we can trace the line}catch(...) {  WY_TERMINATE(""); // so we can trace the line};// [Cancel Point]//// [Syn] The created thread function. tmain() is invoked from inside.//// [Ret] Pointer to _exit_obj//void * Wy_Thread::wy_thread_begin_func(Wy_Thread *obj_ptr){ // Syncronize with begin() by waiting for Active state // begin() may cancel this thread because it may fail in its latter // processing after the thread had been created // {   WyLock aa(obj_ptr->_mtx);   #ifndef NDEBUG    if(obj_ptr->_thrd_id!=::pthread_self()) {  // assertion check      WY_TERMINATE("");    }   #endif } try {   ::pthread_testcancel();   // syncronizing purpose   return obj_ptr->_tmain_finish( obj_ptr->tmain() ); } catch(...) {   // assert: stack unwound from obj_ptr->tmain()   //  (_exit_obj is reset the same)   //   obj_ptr->_tmain_finish( obj_ptr->_exit_obj );   throw; }; // UNREACHABLE};extern "C" inline void * wy__thread_begin_func_c__(void* obj_ptr){  return Wy_Thread::wy_thread_begin_func(                    reinterpret_cast<Wy_Thread *>(obj_ptr));};// [Non-cancellation Point]//WyRet Wy_Thread::begin(void)try {  WyRet r;  WyLock aa_toltab( wy__toltab_ptr->mutex() );   // lock toltab first  WyLock aa_this(_mtx);  if(_in_destroy==true) {    WY_THROW( WyRet() );  }  if(_thrd_stat!=Null) {    WY_RETURN(Wym_EBADF);  }  if(wy__toltab_ptr->size()>=Wy_Thread::Max_Threads) {    WY_RETURN(Wym_ENFILE);  }  // preset return status  //  (_thrd_id will be set by pthread_create)  _thrd_stat=Active;  _exit_obj=Wym_ETHRDCAN; WY_HERE(_exit_obj);  int v;  try {    // assert: _thrd_id==default    if((v=::pthread_create(&_thrd_id,&_thrd_attr,                            wy__thread_begin_func_c__,                           static_cast<void*>(this)))!=0) {       // ENOMEM can return, which is not in the manpage       //       this->_reset_avars();       _thrd_stat_cond.broadcast();       WY_RETURN( WyRet(v) );    }    #ifdef WY_DEBUG    {      WyLock atmp(wy_act_mutex);      ++wy_created_cnt;      if(wy_created_cnt<wy_joined_cnt) {        WY_TERMINATE("");      }      const size_t act=wy_created_cnt-wy_joined_cnt;      if(act>wy_act_max) {        wy_act_max=act;      }    }    #endif    // Check that _thrd_id is not the value identical to the default id    // Refer to definition of Wy_ThreadID::Default_ThreadID.    //    if(_thrd_id==Wy_ThreadID::Default_ThreadID) {      WY_THROW( WyRet() ); // assertion failure    }    WyRet r( wy__toltab_ptr->add(this,_thrd_id) );    if(r!=Ok) {      WY_THROW(r);    // no error with wy__toltab_ptr->add(..) is expected    }  }  catch(...) {    if(_thrd_id!=Wy_ThreadID::Default_ThreadID) {      while((v=::pthread_cancel(_thrd_id))!=0) {        // ref. note5        if(v==EAGAIN) {          continue;     // no yield();        }        WY_THROW( WyRet(v) );    // ESRCH (or others not documented)      };      if(v==0) {        NoCancel noc;        while(_thrd_stat==Active) {          // cancel_point          if((r=_thrd_stat_cond.wait(aa_this))!=Ok) {            WY_THROW(r); // Wym_EINVAL          }        }      }    }    this->_reset_avars();    _thrd_stat_cond.broadcast();    throw;  };  _thrd_stat_cond.broadcast();  return(Ok);}catch(const WyLock::Reply& e) {#ifdef WY_DEBUG Wy::cerr << Wy::wrd(e) << '\n';#endif  WY_THROW( WyRet(e) );}catch(const WyRet& e) {#ifdef WY_DEBUG Wy::cerr << Wy::wrd(e) << '\n';#endif  WY_THROW( WyRet(e) );};// [Non-cancellation Point]//WyRet Wy_Thread::cancel(void)try {  WyLock aa(_mtx);  if(_in_destroy==true) {    WY_THROW( WyRet() );  }  // Detect earily (in case default _thrd_id is meaningful to pthread)  //  if(_thrd_id==Wy_ThreadID::Default_ThreadID) {    WY_RETURN(Wym_ESRCH);  }  if(::pthread_equal(_thrd_id,::pthread_self())) {    WY_RETURN(Wym_EPERM);  // thread can not cancel itself  }    int v;  while((v=::pthread_cancel(_thrd_id))!=0) {    // ref. note5    if(v==EAGAIN) {      Wy__Base::yield();      continue;    }    if(v==ESRCH) {  // note9      // may happen sometimes (chk_thread2): cancelled running thread      // effects in the meanwhile *this is being destroyed      // See also ~Wy_Thread()      //      WY_RETURN( WyRet(v) );    }    WY_THROW( WyRet(v) ); // ESRCH (or others not documented)  }  return(Ok);}catch(const WyLock::Reply& e) {#ifdef WY_DEBUG Wy::cerr << Wy::wrd(e) << '\n';#endif WY_THROW( WyRet(e) );}catch(const WyRet& e) {#ifdef WY_DEBUG Wy::cerr << Wy::wrd(e) << '\n';#endif WY_THROW( WyRet(e) );};// [Cancel Point]//WyRet Wy_Thread::wait_not(ThreadState state)try { WyLock aa(_mtx); WyRet r;  if(_in_destroy==true) {    WY_THROW( WyRet() );  } if(_thrd_id!=Wy_ThreadID::Default_ThreadID) {   if(::pthread_equal(_thrd_id,::pthread_self())) {     // thread cannot wait for the state of itself     WY_RETURN(Wym_EPERM);   } } switch(state) {   case Active: {               while(_thrd_stat==Active) {                 // cancel_point                 if((r=_thrd_stat_cond.wait(aa))!=Ok) {                   WY_THROW( WyRet(r) ); // Wym_EINVAL                 }               }               }; break;   case Null: {               while(_thrd_stat==Null) {                 // cancel_point                 if((r=_thrd_stat_cond.wait(aa))!=Ok) {                   WY_THROW( WyRet(r) ); // Wym_EINVAL                 }               }              }; break;   case Stopped: {               while(_thrd_stat==Stopped) {                 // cancel_point                 if((r=_thrd_stat_cond.wait(aa))!=Ok) {                   WY_THROW( WyRet(r) ); // Wym_EINVAL                 }               }               }; break;   default:        WY_THROW( WyRet() ); }; return(Ok);}catch(const WyLock::Reply& e) {#ifdef WY_DEBUG Wy::cerr << Wy::wrd(e) << '\n';#endif WY_THROW( WyRet(e) );}catch(const WyRet& e) {#ifdef WY_DEBUG Wy::cerr << Wy::wrd(e) << '\n';#endif WY_THROW( WyRet(e) );};// [Non-cancellation Point]//Wy_ThreadID Wy_Thread::thread_self(void){ //::pthread_once(&wy__toltab_once_var, wy__toltab_once_func); return Wy_ThreadID(::pthread_self()); };// [Cancel Point]//void Wy_Thread::cancel_point(void){ //::pthread_once(&wy__toltab_once_var, wy__toltab_once_func); ::pthread_testcancel(); };// [Non-cancellation Point]//WyRet Wy_Thread::yield(void){ ::pthread_once(&wy__toltab_once_var, wy__toltab_once_func); const int v=Wy__Base::yield(); if(v==0) {   return(Ok); } WY_RETURN( WyRet(v) );};// [Non-cancellation Point]//// Note: speed remains an issue with this member//Wy_Thread* Wy_Thread::tbase_ptr(void)try { ::pthread_once(&wy__toltab_once_var, wy__toltab_once_func); WyLock aa( wy__toltab_ptr->mutex() ); const Wy_Thread* retv( wy__toltab_ptr->find(Wy_Thread::thread_self()) ); return(const_cast<Wy_Thread*>(retv));}catch(const WyRet& e) {#ifdef WY_DEBUG Wy::cerr << Wy::wrd(e) << '\n';#endif WY_THROW( WyRet(e) );};// [Non-cancellation Point]//void Wy_Thread::exit(WyRet exit_ret)try { ::pthread_once(&wy__toltab_once_var, wy__toltab_once_func); WyRet r; const Wy_ThreadID ctid( Wy_Thread::thread_self() ); WyLock aa_toltab(wy__toltab_ptr->mutex()); const Wy_Thread* optr=wy__toltab_ptr->find(ctid); if(optr==NULL) {   //   // Note: If the calling thread is not created by Wy_Thread,   //       ::pthread_exit(r.c_repcode()) is called.   //   ::pthread_exit((void*)(exit_ret->c_repcode())); } WyLock aa_optr(optr->_mtx); #ifndef NDEBUG  if(optr->_thrd_stat!=Active) {    // assertion: thread tmain() always sees Active state       WY_TERMINATE("");  } #endif const_cast<Wy_Thread*>(optr)->_exit_obj.reset(exit_ret); ::pthread_exit( &(const_cast<Wy_Thread*>(optr)->_exit_obj) );}catch(const WyLock::Reply& e) {#ifdef WY_DEBUG Wy::cerr << Wy::wrd(e) << '\n';#endif WY_THROW( WyRet(e) );}catch(const WyRet& e) {#ifdef WY_DEBUG Wy::cerr << Wy::wrd(e) << '\n';#endif WY_THROW( WyRet(e) );}catch(const std::bad_alloc&) {#ifdef WY_DEBUG Wy::cerr << "std::bad_alloc\n";#endif WY_THROW( WyRet() );}catch(const std::exception&) {#ifdef WY_DEBUG Wy::cerr << "std::exception\n";#endif WY_THROW( WyRet() );};// [Non-cancellation Point]//size_t Wy_Thread::active_threads(void)try { ::pthread_once(&wy__toltab_once_var, wy__toltab_once_func); WyRet r; if((r=wy__toltab_ptr->mutex().lock())!=Ok) {   WY_THROW(r); } const size_t retv( wy__toltab_ptr->size() ); if((r=wy__toltab_ptr->mutex().unlock())!=Ok) {   WY_THROW(r); } return(retv);}catch(const WyRet& e) {#ifdef WY_DEBUG Wy::cerr << Wy::wrd(e) << '\n';#endif WY_THROW( WyRet(e) );};// note: function form to limit usecases (so far)//size_t Wy_Thread::max_threads(void) WY__TSPC(){ return Max_Threads;};//----------------------------------------------------------------------------/* note2: Wy_Thread assert the function call never fail:        :::pthread_setcancelstate( PTHREAD_CANCEL_ENABLE: PTHREAD_CANCEL_DISABLE                         , &oldstate)        it might be better let this function always succeed. note5:       ::pthread_cancel found to return EAGAIN (on RH Linux9.0)       while man. indicates only fail on ESRCH. note6: Wy_Thread created threads always returns &_exit_obj, which is        already set with desired value except cancelled.        (So, value of PTHREAD_CANCELED cannot be any valid address, it is -1         as I saw the source) note8: _thrd_stat transition general rule:          Null -> Active    .. by begin()          Active -> Stopped .. by _tmain_finish()          * -> Null         .. by reset() note9: In rare testing situation, ESRCH may occur. Dont know how, but defensive           begin(void)+   _tmain_finish+      reset(void)+                      | ^                      v |             Stopped                  +----         ----+ _thrd_stat: Active   +---         ---+             ----+             Null   --+               .                 +-----                      ...             . _thrd_id:    valid   +---           --+            ----+            invalid --+               .+--              +----- real thread          .+-+--         --+                    ---+-+             +----*/

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -