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

📄 chk_thread2.cpp

📁 一个不错
💻 CPP
字号:
/* Copyright is licensed under GNU LGPL.                 by I.J.Wang 2006   Test Wy_Thread Part-2: cancellation test         Build: make chk_thread2   Warning: This check does not get Ok result (chk_thread1 is Ok)*/#include "wy_thread.h"#include "wy_uty.h"#include "wytimespec.h"#include "wyregfile.h"#include "wychrfile.h"#include <exception>      // for set_terminate#include <cstdlib>#if WY_THREAD_VERSION!=31#error Test code is for WY_THREAD_VERSION 31#endiftypedef void (*PFV)(void);// Each thread begun increases ent_cnt by one//static int ent_cnt=0;static size_t peak_threads=0;static WyMutex ent_cnt_mtx;// Each thread exits increases lft_cnt by one//static int lft_cnt=0; static WyMutex lft_cnt_mtx;// Max. fd measuredstatic int peak_fd=0;static WyMutex fd_cnt_mtx;static void term_msg(void){ Wy::cerr << "term_msg entered\n";};static void unexp_msg(void){ Wy::cerr << "unexp_msg entered\n"; try { throw; } catch(const WyRet& e) {   Wy::cerr << Wy::wrd(e) << '\n';   //throw; };};// The thread class to run the test//class TestThread2 : public Wy_Thread {    int _lev;      // level, 0<=terminal node    int _nid;    WyMutex t2_mtx;    void tmain_enter(void)         {           WyMutex::lock(ent_cnt_mtx);           ++ent_cnt;           const size_t tt=Wy_Thread::active_threads();           if(tt>peak_threads) {             peak_threads=tt;           }           WyMutex::unlock(ent_cnt_mtx);         };    void tmain_leave(void)         {           WyMutex::lock(lft_cnt_mtx);           ++lft_cnt;           WyMutex::unlock(lft_cnt_mtx);         };    void tmain_t1(void);    void tmain_t2(void);  protected:   virtual WyRet tmain(void);  public:    // Construct object ready to run the thread with specified exit type and code    //    TestThread2() : Wy_Thread() , _lev(0), _nid(-1) {};    ~TestThread2() throw();    WyRet begin(int id, int level)          {           WyRet r;           {             WyLock aa(t2_mtx);    // lock data members (for test)             _nid=id;             _lev=level;             r=Wy_Thread::begin();            }           return(r);         };};TestThread2::~TestThread2() throw()try { Wy_Thread::tmain_close(); Wy_Thread::tmain_close();   // simulate multi-layer (should be trival effect)}catch(const WyRet& e) { Wy::cerr << Wy::wrd(e) << '\n'; throw;}catch(...) { Wy::cerr << "~TestThread2()\n"; throw;};WyRet TestThread2::tmain(void)try { //std::set_terminate(unexp_msg);  causing long dump //std::set_unexpected(term_msg); tmain_enter(); if(thread_self().is_default()) {   WY_TERMINATE(""); } {   TestThread2 *tptr=dynamic_cast<TestThread2*>( tbase_ptr() );   if(tptr==NULL) {     WY_TERMINATE("");   }   if(tptr!=dynamic_cast<TestThread2*>(this)) {     Wy::cerr << "tbase_ptr()=" << tbase_ptr()               << ", this=" << this               << '\n';     WY_TERMINATE("");   }   WyLock aa(t2_mtx);   if((tptr->_nid!=_nid)||(tptr->_lev!=_lev)) {     Wy::cerr << "main_thread_id()=" << wy_main_thrd_id._pthread_id() << '\n';     Wy::cerr << "\nthread_self()=" << ::pthread_self() << '\n';     Wy::cerr << "tptr: _nid=" << tptr->_nid << ", " << " _lev=" << tptr->_lev              << ", thread_id()=" << tptr->thread_id()._pthread_id() << '\n';          Wy::cerr << "this: _nid=" << this->_nid << ", " << " _lev=" << this->_lev               << ", thread_id()=" << this->thread_id()._pthread_id() << '\n';     WY_TERMINATE("");   } } // make child thread of the next level // TestThread2 child; {   WyLock aa(t2_mtx);   if(_lev>0) {     WyRet r( child.begin(_nid*10,_lev-1) );     if(r!=Ok) {       WY_THROW(r);     }   } } // loop to make the test code consume more time // for(int i=0; i<50; ++i) {   //Wy::sleep( WyTimeSpec(0,2000000) );   tmain_t1();   tmain_t2(); } tmain_leave(); return(Ok);}catch(const WyRet& e) { Wy::cerr << Wy::wrd(e) << '\n'; tmain_leave(); return(e);}catch(...) {  tmain_leave();  throw;};// use rdonly functions that are cancellation points//void TestThread2::tmain_t1(void)try { const WyCSeg FData="/* Copyright is licensed under GNU LGPL.                 by I.J.Wang 2006\n"; WyRet r; WyRegFile tfile(__FILE__,O_RDONLY); WyStr str; size_t n_rd;  WyMutex::lock(fd_cnt_mtx); if(tfile.fh().fd()>peak_fd) {   peak_fd=tfile.fh().fd(); } WyMutex::unlock(fd_cnt_mtx); //tfile.set_pos(0); if((r=tfile.read(str,FData.size(),n_rd))!=Ok) {   Wy::cerr << Wy::wrd(r) << '\n'; } if(n_rd!=str.size()) {   WY_TERMINATE(""); } if(n_rd!=FData.size()) {   WY_TERMINATE(""); } if(str!=FData) {   WY_TERMINATE(""); } // reset if((r=tfile.reset(__FILE__,O_RDONLY))!=Ok) {   WY_THROW(r); } // read(void*,size_t,size_t&) n_rd=0; if((r=tfile.read(&str[0],FData.size(),n_rd))!=Ok) {   Wy::cerr << Wy::wrd(r) << '\n'; } if(n_rd!=FData.size()) {   WY_TERMINATE(""); } str._setsize(n_rd); if(str!=FData) {   WY_TERMINATE(""); } // _read_till tfile.set_pos(0); str.reset(); n_rd=0; if((r=tfile._read_till(str,FData.size(),n_rd,'\n'))!=Ok) {   Wy::cerr << Wy::wrd(r) << '\n'; } if(n_rd!=str.size()) {   WY_TERMINATE(""); } if(n_rd!=FData.size()) {   WY_TERMINATE(""); } if(str!=FData) {   WY_TERMINATE(""); } // Wy::full_read tfile.set_pos(0); str.reset(); n_rd=0; if((r=Wy::full_read(tfile,str,FData.size()))!=Ok) {   Wy::cerr << Wy::wrd(r) << '\n'; } if(str!=FData) {   WY_TERMINATE(""); } // This functions are just for cancellation point test Wy::sleep( WyTimeSpec(0,1) );}catch(const WyRet& e) { Wy::cerr << Wy::wrd(e) << '\n'; throw;}catch(...) { #ifdef WY_DEBUG Wy::cerr << "t1 "; #endif throw;};// write to /dev/null//void TestThread2::tmain_t2(void)try { WyByteFlow bf("/dev/null",O_WRONLY); WyRet r; size_t n_wr; WyMutex::lock(fd_cnt_mtx); if(bf.fh().fd()>peak_fd) {   peak_fd=bf.fh().fd(); } WyMutex::unlock(fd_cnt_mtx); if((r=bf.write(&r,sizeof(r),n_wr))!=Ok) {   Wy::cerr << Wy::wrd(r) << '\n'; } if((r=bf._tcdrain())!=Ok) { } // strnum/WyTimeSpec {   WyTimeSpec tm1("1.234e2");   WyTimeSpec tm2(123,400000000LL);   if(tm1!=tm2) {     WY_THROW( WyRet() );   }   tm1.reset();   tm2.reset(); }}catch(const WyRet& e) { Wy::cerr << Wy::wrd(e) << '\n'; throw;}catch(...) { #ifdef WY_DEBUG Wy::cerr << "t2 "; #endif throw;};// Check default thread object properties//static WyRet chk_default_attr(TestThread2& thrd){ WyRet r; if(thrd.is_default()==false) {   WY_RETURN(Wym_E127); } if(thrd.thread_state()!=Wy_Thread::Null) {   WY_RETURN(Wym_E127); } if((r=thrd.wait_not(Wy_Thread::Active))!=Ok) {   WY_RETURN(Wym_E127); } if((r=thrd.wait_not(Wy_Thread::Stopped))!=Ok) {   WY_RETURN(Wym_E127); } if(!thrd.exitcode().is_default()) {   WY_RETURN(Wym_E127); } return(Ok);};// Test in Tight Loop//static void t_tight_loop(void){ const int NumOfThrds=50;      // 300 would get ENOMEM on my playform const int LoopCount=10000; TestThread2 thrTab[NumOfThrds]; WyRet r; // Check all thread objects in thrTab[] are default // for(int i=0; i<NumOfThrds; ++i) {   if((r=chk_default_attr(thrTab[i]))!=Ok) {     WY_THROW(r);   } } // The tight loop create/cancel an entry in thrTab[] by random hit // Wy::cout << "count=" << LoopCount << " ...wait\n"; //std::srand( Wy::now().nano() ); for(int cnt=0; cnt<LoopCount; ++cnt) {   if((cnt%(LoopCount/75))==0) { Wy::cout << '.'; }  // notify alive   Wy::sleep( WyTimeSpec(0,500000) );     // sleep 0.5 mS   // Generate random index for each loop   const int idx=(int)(((NumOfThrds-0.1)*std::rand())/(double)RAND_MAX);   #ifdef WY_DEBUG   Wy::cerr << ' ' << idx;   #endif   TestThread2& thrd=thrTab[idx];   switch(thrd.thread_state()) {     case Wy_Thread::Stopped:                   #ifdef WY_DEBUG                   Wy::cerr << 's';                   #endif                   if((r=thrd.reset())!=Ok) {  // bring to Null state                     WY_THROW(r);                   }                   break;     case Wy_Thread::Null:                   // Create a thread if the entry is in Null state                   //                   #ifdef WY_DEBUG                   Wy::cerr << 'B';                   #endif                   while((r=thrd.begin(idx,1))!=Ok) {                     if(r==Wym_EAGAIN) {                       continue;                     }                     WY_THROW(r);                   }                   break;     case Wy_Thread::Active:                   // Cancel the thread                   // (note: the thread may have terminated)                   //                   #ifdef WY_DEBUG                   Wy::cerr << 'C';                   #endif                   thrd.cancel();                   break;     default:          WY_THROW( WyRet() );   // should not get here   } } #ifdef WY_DEBUG Wy::cerr << "\nloop end\n"; #endif/* { // print statistics before reset   WyLock a1(ent_cnt_mtx);   WyLock a2(lft_cnt_mtx);   WyLock a3(fd_cnt_mtx);   Wy::cerr << "\nent=" << ent_cnt << ", lft=" << lft_cnt << '\n';   Wy::cout << "max_threads()= " << Wy_Thread::max_threads() << '\n';   Wy::cout << "maximal testing threads= " << peak_threads << '\n';   Wy::cout << "maximal measured fd= " << peak_fd << '\n'; }*/ for(int i=0; i<NumOfThrds; ++i) {   #ifdef WY_DEBUG   Wy::cerr << ' ' << i;   #endif   thrTab[i].reset(); } while(Wy_Thread::active_threads()!=0) {  // should be no more active thread   Wy::cerr << " active_threads()=" << Wy_Thread::active_threads() << '\n';   WY_THROW( WyRet() ); } { // print statistics   WyLock a1(ent_cnt_mtx);   WyLock a2(lft_cnt_mtx);   WyLock a3(fd_cnt_mtx);   Wy::cout << "\nent=" << ent_cnt << ", lft=" << lft_cnt << '\n';   Wy::cout << "max_threads()= " << Wy_Thread::max_threads() << '\n';   Wy::cout << "maximal testing threads= " << peak_threads << '\n';   Wy::cout << "maximal measured fd= " << peak_fd << '\n'; }};int main(void)try { Wy::cout << "Checking wy_thread.cpp, tight loop. "; t_tight_loop(); Wy::cout << "Checked Ok\n"; return(0);}catch(const WyRet& e) { Wy::cerr << Wy::wrd(e) << '\n'; return(-1);}catch(...) { Wy::cerr << "unknown unwind\n"; return(-1);};

⌨️ 快捷键说明

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