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

📄 wy_thread.cpp

📁 一个不错
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/* Copyright is licensed under GNU LGPL.                 by I.J.Wang 2003.active_threads()=1General error, chk_thread2.cpp(329)pass: 24,2,11,20,11,16,17,2,4程式記憶體區段錯誤   ./chk_thread2pass:24,3,2reset halt:pass: 5,23,10,2,9,4,4,3,5,18,1,1,6,3,6*/#define WYLIB_SOURCE#include "wy_thread.h"#include <pthread.h>#include <new>        // bad_alloc#ifdef WY_DEBUG#include "wy_uty.h"#endifconst char Wy_Thread::class_name[]="Wy_Thread";// Because no document found for the value of ::pthread_t for no thread.// pick 0 for it, so far so good (the value it is initialized does not work)//static const ::pthread_t TID_NoThread=0;const ::pthread_t Wy_ThreadID::Default_ThreadID=TID_NoThread;Wy_ThreadID::Wy_ThreadID() WY__TSPC()  : _tid(Default_ThreadID) {};Wy_ThreadID::Wy_ThreadID(const Wy_ThreadID& src) WY__TSPC()  : _tid(src._tid) {};    Wy_ThreadID::Wy_ThreadID(::pthread_t tid) WY__TSPC() : _tid(tid) {};Wy_ThreadID::Wy_ThreadID(Wy_ThreadID& src, Wy::ByMove_t) WY__TSPC() : _tid(src._tid){};::pthread_t Wy_ThreadID::_pthread_id(void) const WY__TSPC(){ return _tid; };bool Wy_ThreadID::is_default(void) const WY__TSPC(){ return _tid==Default_ThreadID; };void Wy_ThreadID::reset(void) WY__TSPC(){ _tid=Default_ThreadID; };void Wy_ThreadID::reset(const Wy_ThreadID& src) WY__TSPC(){ _tid=src._tid; };void Wy_ThreadID::reset(::pthread_t tid) WY__TSPC(){ _tid=tid;};const Wy_ThreadID& Wy_ThreadID::operator =(const Wy_ThreadID& tid) WY__TSPC(){ _tid=tid._tid; return(*this); };bool Wy_ThreadID::operator==(Wy_ThreadID id) const WY__TSPC(){ return _tid==id._tid; };bool Wy_ThreadID::operator!=(Wy_ThreadID id) const WY__TSPC(){ return _tid!=id._tid; };bool Wy_ThreadID::_thread_equal(Wy_ThreadID t1, Wy_ThreadID t2) WY__TSPC(){ return ::pthread_equal(t1._tid,t2._tid); };//-----------------------------------------------------------------static ::pthread_once_t wy__toltab_once_var=PTHREAD_ONCE_INIT;// [Internal] Array item of Wy__TOLTab//            Pair of Wy_ThreadID and Wy_Thread object pointer for association////  Note: The association should be 1-1, or result not predictable//class Wy__TOLItem {  public:    // [Syn] construct default object    //    //  tol_ptr() = NULL    //  tol_tid() = Wy_ThreadID()    //    inline Wy__TOLItem() WY__NOTHROW__ : _tid(),_optr(NULL) {};    inline Wy__TOLItem(const Wy__TOLItem& src) WY__NOTHROW__        : _tid(src._tid),_optr(src._optr) {};    inline Wy__TOLItem(Wy_ThreadID id, const Wy_Thread* optr) WY__NOTHROW__        : _tid(id),_optr(optr) {};    inline void reset(void) WY__NOTHROW__         { _tid.reset(); _optr=NULL; };    inline void reset(const Wy__TOLItem& src) WY__NOTHROW__          { _tid.reset(src._tid); _optr=src._optr; }; // self-ops ok    inline void reset(Wy_ThreadID id, const Wy_Thread* optr) WY__NOTHROW__          {  _tid.reset(id); _optr=optr; };    inline bool is_default(void) const WY__NOTHROW__         { return _optr==NULL; };    inline const Wy_Thread* tol_ptr(void) const WY__NOTHROW__         { return _optr; };    inline Wy_ThreadID tol_tid(void) const WY__NOTHROW__         { return _tid; };  private:    Wy_ThreadID _tid;    const Wy_Thread* _optr;};// [Internal] class of set of Wy__TOL ////  Note: Exactly one instance(wy__toltab_ptr) of this class is declared////  Note: All member access should acquire the lock first//class Wy__TOLTab {    size_t _find_idx(Wy_ThreadID tid) WY__NOTHROW__         {           size_t i=0;           for( ; (i<_tabsize)&&(_tab[i].tol_tid()!=tid); ++i) { // value cmp           };           return(i);         };  public:    Wy__TOLTab() WY__NOTHROW__       : _tabsize(0) {};    // [Syn] Get mutex of *this    //    // [Ret] reply    //    WyMutex& mutex(void) WY__NOTHROW__         { return _mtx; };    // [Syn] Get the number of entries    //    // [Ret] number of Wy__TOL entries *this is handling    //    size_t size(void) const WY__NOTHROW__         { return _tabsize; };    // [Syn] Add entry<Wy_Thread pointer,Wy_ThreadID>    //    //       Note: 0. tid is used as the key    //             1. tid must be equal to optr->thread_id()    //                (this member does not dereference optr)    //    // [Ret] Ok          entry added    //       Wym_EEXIST  tid already in *this    //       Wym_FAULT   optr is NULL    //       Wym_ENOSPC  maximal number of threads reached    //    WyRet add(const Wy_Thread* optr,Wy_ThreadID tid)         {           if(optr==NULL) {             return(Wym_EINVAL);           }           if(this->_find_idx(tid)<_tabsize) {             WY_RETURN( Wym_EEXIST );           }           if(_tabsize>=Wy_Thread::Max_Threads) {             WY_RETURN(Wym_ENOSPC);           }           _tab[_tabsize++].reset(tid,optr);           return(Ok);         };    // [Syn] Remove the entry whose Wy_ThreadID is identical to tid    //       If no entry (tid,*) in *this, no effect.    //    bool remove(Wy_ThreadID tid) WY__NOTHROW__         {           const size_t i( this->_find_idx(tid) );           if(i>=_tabsize) {             return(false);        // tid not in tab           }           _tabsize--;           _tab[i].reset(_tab[_tabsize]);           return(true);         };    // [Syn] Find entry whose Wy_ThreadID is identical to tid    //       and return the Wy_Thread* associates with it    //    // [Ret] The Wy_Thread* associates with tid    //       NULL, if no item found    //    const Wy_Thread* find(Wy_ThreadID tid) WY__NOTHROW__         {           const size_t i( this->_find_idx(tid) );           if(i>=_tabsize) {             return(NULL);        // tid not in tab           }           return _tab[i].tol_ptr();         };  private:    Wy__TOLItem _tab[Wy_Thread::Max_Threads];    size_t _tabsize;    mutable WyMutex _mtx;} static *wy__toltab_ptr=NULL;extern "C" void wy__toltab_once_func(void){ try {   wy__toltab_ptr= new Wy__TOLTab();  // note: never free'd } catch(...) {   WY_TERMINATE(""); };};WyStr Wy::wrd(const Wy_ThreadID& tid)try { WyStr v("TID_"); // describe Wy_ThreadID in hexidecimal number  WyRet r=Wy::_catstr(v,(unsigned)tid._pthread_id(),16); if(r!=Ok) {   WY_THROW( WyStr::Reply(r) ); } return(v); }catch(const WyStr::Reply& e) { if(e==Wym_ENOMEM) {   throw; } WY_THROW( WyRet(e) );};//------------------------------------------------------------------------------#ifdef WY_DEBUG size_t wy_joined_cnt=0; size_t wy_created_cnt=0; size_t wy_act_max=0; WyMutex wy_act_mutex;#endif// tid of main (program startup thread)//const Wy_ThreadID Wy_Thread::wy_main_thrd_id(::pthread_self());::pthread_once_t wy__thread_once_var=PTHREAD_ONCE_INIT;bool Wy_Thread::set_cancelable(bool en){ int oldstate; const int v(::pthread_setcancelstate( en? PTHREAD_CANCEL_ENABLE:                                   PTHREAD_CANCEL_DISABLE , &oldstate)); if(v!=0) {   // man. says only parameter error. which should not happen.   WY_THROW( WyRet(v) ); } return (oldstate==PTHREAD_CANCEL_ENABLE);};Wy_Thread::CancelType Wy_Thread::set_canceltype(CancelType ct){ int oldtype; const int v(::pthread_setcanceltype(ct,&oldtype)); if(v!=0) {   // man. says only parameter error. which should not happen.   WY_THROW( WyRet(v) ); } return(static_cast<CancelType>(oldtype));};extern "C" void wy__thread_once_func(void) WY__TSPC(){ // intended for feature test code, nothing yet.};inline void Wy_Thread::_non_cancellable(void) WY__TSPC(){ if(::pthread_setcancelstate(PTHREAD_CANCEL_DISABLE,NULL)!=0) {   WY_TERMINATE(""); }};// [Syn] Cancel an Active thread and wait for non-Active state//// post: thread state is Null or Stopped (no active thread)//void Wy_Thread::_cleanup_thread(WyLock& aa){  WyRet r;  // Cancel the possibly active thread, and join the thread  //  if(_thrd_stat==Active) {    // Note: Wait forever if the threead is not cancellable.    //    do {      int v;      while((v=::pthread_cancel(_thrd_id))!=0) {        // ref. note5        if(v==EAGAIN) {          Wy__Base::yield();  // probably ok          continue;        }        // ESRCH or others not documented        Wy__Base::put_abnmsg( WyReply(v)->c_repstr() ,__FILE__,__LINE__);        Wy__Base::terminate();      };          // cancel_point      if((r=_thrd_stat_cond.wait(aa))!=Ok) {        WY_THROW(r); // Wym_EINVAL      }    } while(_thrd_stat==Active);  } else if(_thrd_stat==Stopped) {  } else {    // Null (no thread)  };};// [Spc] Wy_Thread relies on pthread. Default thread attributes are:////   detatchstate= PTHREAD_CREATE_DETATCHED//   schedpolicy = SCHED_OTHER (regular, non-realtime)//   schedparam  = 0//   inheritsched= PTHREAD_EXPLICIT_SCHED//   scope       = PTHREAD_SCOPE_SYSTEM//Wy_Thread::Wy_Thread()try : _thrd_stat_cond(), _thrd_stat(Null),      _thrd_id(Wy_ThreadID::Default_ThreadID), _exit_obj(),      _in_destroy(false), _mtx(){ ::pthread_once(&wy__toltab_once_var, wy__toltab_once_func); ::pthread_once(&wy__thread_once_var, wy__thread_once_func); WyLock aa(_mtx); int v;  if((v=::pthread_attr_init(&_thrd_attr))!=0) {    //    // manu says only ENOMEM, linux man just says errno.    //     WY_THROW( Reply(v) );  }  if((v=::pthread_attr_setdetachstate(&_thrd_attr,PTHREAD_CREATE_DETACHED))!=0) {    // man. indicates only EINVAL    WY_THROW( WyRet(v) );  }}catch(const Wy_Thread::Reply&) { throw;}catch(const WyLock::Reply& e) {  WY_THROW( WyRet(e) );}catch(const WyRet& e) { WY_THROW( WyRet(e) );};Wy_Thread::~Wy_Thread() WY__TSPC()try {  //  Wy_Thread destructor is non-cancelable   //  Because the active thread need to access *this   // _non_cancellable(); WyLock aa(_mtx); WyRet r; if(_in_destroy==true) {   WY_TERMINATE("");    // destroy twice } _in_destroy=true; this->_cleanup_thread(aa);  // Cleanup members that need cleanup // const int v=::pthread_attr_destroy(&_thrd_attr); if(v!=0) {   // manu says only EINVAL could happen   Wy__Base::put_abnmsg( WyReply(v)->c_repstr() ,__FILE__,__LINE__);   Wy__Base::terminate(); }}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::exception&) { WY_TERMINATE("");}catch(...) { WY_TERMINATE("");};bool Wy_Thread::is_default(void) consttry { // // _thrd_stat==Null ensures the default state, including //    //   1. _thrd_id==Wy_ThreadID::Default_ThreadID //   2. _exit_obj.is_default() //   3. _in_destroy==false //   4. _thrd_attr is default // WyLock aa(_mtx); return(_thrd_stat==Null);}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_id(void) consttry { WyLock aa(_mtx); return Wy_ThreadID(_thrd_id); }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_Thread::ThreadState Wy_Thread::thread_state(void)try { WyLock aa(_mtx); if(_thrd_stat==Active) {   if(::pthread_equal(_thrd_id,::pthread_self())) {     WY_THROW( Reply(Wym_EPERM) );  // thread can not query it state   } } return _thrd_stat;}catch(const Wy_Thread::Reply&) { throw;}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::exitcode(void) consttry { WyLock aa(_mtx); return(_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) );};// [Non-cancellation Point]WyRet Wy_Thread::reset(void)try {  NoCancel noc;  WyLock aa(_mtx);  if(_in_destroy==true) {    WY_THROW( WyRet() );  }  WyRet r;  // If the created thread is active(running), cancel it.  //  if(_thrd_stat==Active) {    if(::pthread_equal(_thrd_id,::pthread_self())) {      // thread (tmain) is not allowed to reset itself      // rule of libwy says reset() always returns with default object      //      WY_THROW( WyRet() );    }    this->_cleanup_thread(aa);  }  int v;  // Reset thread attr object (destoy and initialize again)  //

⌨️ 快捷键说明

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