📄 chk_thread1.cpp
字号:
/* Copyright is licensed under GNU LGPL. by I.J.Wang 2003 Test Wy_Thread Part-I Basic thread check Build: make chk_thread1*/#include "tsthread.h"#include "wy_atdestroy.h"#include "wy_uty.h"#include <cstdlib>#include <iostream>#if WY_THREAD_VERSION!=31#error Test code is for WY_THREAD_VERSION 31#endif// Check Wy_ThreadIDstatic void chk_threadid(void){ const ::pthread_t SelfID=::pthread_self(); // constructor { Wy_ThreadID t0,t1(t0); if(t0.is_default()==false) { WY_THROW( WyRet() ); } if(t1.is_default()==false) { WY_THROW( WyRet() ); } if(t0!=t1) { WY_THROW( WyRet() ); } if(t0==t1) { } else { WY_THROW( WyRet() ); } if(::pthread_equal(t0._pthread_id(),SelfID)) { WY_THROW( WyRet() ); // assertion failed } if(Wy_ThreadID::_thread_equal(t0,t1)==false) { // default obj's are equ WY_THROW( WyRet() ); } } { Wy_ThreadID t0,t1; t1.reset(SelfID); Wy_ThreadID t2(t1); if(t0.is_default()==false) { WY_THROW( WyRet() ); } if(t1.is_default()) { WY_THROW( WyRet() ); } if(t2.is_default()) { WY_THROW( WyRet() ); } if(t0==t1) { WY_THROW( WyRet() ); } if(t1!=t2) { WY_THROW( WyRet() ); } if(Wy_ThreadID::_thread_equal(t0,t1)==true) { WY_THROW( WyRet() ); } if(Wy_ThreadID::_thread_equal(t1,t2)==false) { WY_THROW( WyRet() ); } } // reset { Wy_ThreadID t0,t1; t1.reset(SelfID); Wy_ThreadID t2(t1); t0.reset(); if(t0.is_default()==false) { WY_THROW( WyRet() ); } t1.reset(); if(t1.is_default()==false) { WY_THROW( WyRet() ); } t1.reset(t2); if(t1.is_default()) { WY_THROW( WyRet() ); } if(t1!=t2) { WY_THROW( WyRet() ); } } // chk move ctor { char buf[2*sizeof(Wy_ThreadID)]; ::memset(buf,0,sizeof(buf)); Wy_ThreadID*p=reinterpret_cast<Wy_ThreadID*>(buf); new(p) Wy_ThreadID(); new(p+1) Wy_ThreadID(*p,Wy::ByMove); if((p+1)->is_default()==false) { (p+1)->~Wy_ThreadID(); WY_THROW( WyRet() ); } (p+1)->~Wy_ThreadID(); }};class T_ErrInfo : public Wy_RepInfo { T_ErrInfo(const T_ErrInfo&); public: T_ErrInfo(const char* cstr) throw() : Wy_RepInfo(cstr) {}; size_t get_reply(char* buf, size_t blen) const throw() { return Wy_RepInfo::get_reply(buf,blen); }; void set_reply(const char* buf, size_t blen) throw() {};};static T_ErrInfo ei("Test Failed");static const WyReply TEST_FAIL(ei);// Check default TsThread object properties//static WyRet chk_default_attr(TsThread& thrd){ Wy_Thread::ThreadState st; WyRet tret; WyRet r; if(thrd.is_default()==false) { WY_RETURN(TEST_FAIL); } st=thrd.thread_state(); if(st!=Wy_Thread::Null) { WY_RETURN(TEST_FAIL); } if(thrd.thread_id().is_default()==false) { WY_RETURN(TEST_FAIL); } if((r=thrd.cancel())!=Wym_ESRCH) { WY_RETURN(TEST_FAIL); } if((r=thrd.wait_not(Wy_Thread::Stopped))!=Ok) { WY_RETURN(TEST_FAIL); } if((r=thrd.wait_not(Wy_Thread::Active))!=Ok) { WY_RETURN(TEST_FAIL); } tret=thrd.exitcode(); if(!tret.is_default()) { WY_RETURN(TEST_FAIL); } { Wy_Thread::CancelType ct( thrd.set_canceltype(Wy_Thread::Deferred) ); if(ct!=Wy_Thread::Deferred) { thrd.set_canceltype(ct); WY_RETURN(TEST_FAIL); } } return(Ok);};// begin() the default TsThread thrd configured as the arguments// and chk for expected behavior//static void ck_thread_0(TsThread& thrd,TsThread::ExitType etype,WyReply ec,WyTimeSpec delay)try { WyRet r; if((r=chk_default_attr(thrd))!=Ok) { WY_THROW(r); } if((r=thrd.begin())!=Ok) { WY_THROW(r); } if((r=thrd.begin())!=Wym_EBADF) { WY_THROW(r); } const WyTimeSpec TM0( Wy::now() ); WyTimeSpec tm; if((r=thrd.wait_not(Wy_Thread::Null))!=Ok) { WY_THROW(r); } if(thrd.thread_state()!=Wy_Thread::Active) { WY_THROW( WyRet() ); } if(thrd.thread_id().is_default()) { WY_THROW( WyRet() ); } switch(etype) { case TsThread::Return: { if((r=thrd.wait_not(Wy_Thread::Active))!=Ok) { WY_THROW(r); } tm= Wy::now()-TM0; if(thrd.thread_state()!=Wy_Thread::Stopped) { WY_THROW( WyRet() ); } if(thrd.exitcode()!=ec) { WY_THROW( thrd.exitcode() ); } if(((tm-delay).abs())>WyTimeSpec(0,50000000)) { Wy::cerr << "Inaccurate delay: > 0.05 second\n"; //WY_THROW( WyRet() ); } if((r=thrd.reset())!=Ok) { WY_THROW(r); } if((r=chk_default_attr(thrd))!=Ok) { WY_THROW(r); } }; break; case TsThread::Exit: { if((r=thrd.wait_not(Wy_Thread::Active))!=Ok) { WY_THROW(r); } tm= Wy::now()-TM0; if(thrd.thread_state()!=Wy_Thread::Stopped) { WY_THROW( WyRet() ); } if(thrd.exitcode()!=ec) { WY_THROW( thrd.exitcode() ); } if(((tm-delay).abs())>WyTimeSpec(0,50000000)) { Wy::cerr << "Inaccurate delay: > 0.05 second\n"; //WY_THROW( WyRet() ); } if((r=thrd.reset())!=Ok) { WY_THROW(r); } if((r=chk_default_attr(thrd))!=Ok) { WY_THROW(r); } }; break; case TsThread::Cancel: { Wy::sleep(delay); if((r=thrd.cancel())!=Ok) { WY_THROW(r); } if((r=thrd.wait_not(Wy_Thread::Active))!=Ok) { WY_THROW(r); } tm= Wy::now()-TM0; if(thrd.thread_state()!=Wy_Thread::Stopped) { WY_THROW( WyRet() ); } if(thrd.exitcode()!=ec) { WY_THROW( thrd.exitcode() ); } if(((tm-delay).abs())>WyTimeSpec(0,50000000)) { Wy::cerr << "Inaccurate delay: > 0.05 second\n"; //WY_THROW( WyRet() ); } if((r=thrd.reset())!=Ok) { WY_THROW(r); } if((r=chk_default_attr(thrd))!=Ok) { WY_THROW(r); } }; break; case TsThread::Reset: { Wy::sleep(delay); if((r=thrd.reset())!=Ok) { WY_THROW(r); } tm= Wy::now()-TM0; if(((tm-delay).abs())>WyTimeSpec(0,50000000)) { Wy::cerr << "Inaccurate delay: > 0.05 second\n"; //WY_THROW( WyRet() ); } if((r=chk_default_attr(thrd))!=Ok) { WY_THROW(r); } }; break; default: WY_TERMINATE(""); }; // chk reset() again (diff code path) if((r=thrd.reset())!=Ok) { WY_THROW(r); } if((r=chk_default_attr(thrd))!=Ok) { WY_THROW(r); }}catch(const WyRet& e) { Wy::cerr << Wy::wrd(e) << '\n'; throw;}catch(...) { throw;};static void ck_thread_a(void){ const WyTimeSpec TDelay(0,500000000); // 0.5 sec WyRet r; if(Wy_Thread::max_threads()!=512) { WY_THROW( WyRet() ); } // chk stopped by return { TsThread thrd1(TsThread::Return,Wym_EIO,TDelay); ck_thread_0(thrd1,TsThread::Return,Wym_EIO,TDelay); } // chk stopped by exit { TsThread thrd1(TsThread::Exit,Wym_EINVAL,TDelay); ck_thread_0(thrd1,TsThread::Exit,Wym_EINVAL,TDelay); } // chk stopped by cancel { TsThread thrd1(TsThread::Cancel,Wym_ETHRDCAN,TDelay); ck_thread_0(thrd1,TsThread::Cancel,Wym_ETHRDCAN,TDelay); } // chk stopped by reset { TsThread thrd1(TsThread::Reset,WyRet(),TDelay); ck_thread_0(thrd1,TsThread::Reset,WyRet(),TDelay); } // chk stopped by destroy TsThread object { { TsThread thrd1(TsThread::Reset,WyRet(),TDelay); if((r=thrd1.begin())!=Ok) { WY_THROW( WyRet() ); } } }};// non Wy_Thread created thread function//static void* nw_thread_routine(void* arg){ // chk tbase_ptr() if(Wy_Thread::tbase_ptr()!=0) { WY_TERMINATE(""); } // chk thread_self() const ::pthread_t SelfID=::pthread_self(); if(Wy_ThreadID::_thread_equal(Wy_Thread::thread_self(),SelfID)==false) { WY_THROW( WyRet() ); } if(::pthread_equal(Wy_Thread::thread_self()._pthread_id(),SelfID)==0) { WY_THROW( WyRet() ); } // chk cancel_point(), just verify available Wy_Thread::cancel_point(); // chk exit(WyRet) Wy_Thread::exit( WyRet(Wym_E41) );};// chk some static member in none Wy_Thread created thread//static void ck_thread_nwy(void){ pthread_t tid; void* tres; int v; if((v=::pthread_create(&tid,NULL,nw_thread_routine,NULL))!=0) { WY_THROW( WyRet(WyReply(v)) ); } if((v=::pthread_join(tid, &tres))!=0) { WY_THROW( WyRet(WyReply(v)) ); } if((int)tres!=Wym_E41->c_repcode()) { WY_THROW( WyRet() ); }};//-------------------// HThread runs ck_thread_a in tmain()//class HThread : public Wy_Thread { public: HThread() : Wy_Thread() {}; ~HThread() throw() { Wy_Thread::tmain_close(); }; protected: WyRet tmain(void) { ck_thread_a(); return(Ok); };};static WyRet exaust_threads(void){ const WyTimeSpec TDelay(0,10000000); // 0.01 sec WyRet r; TsThread thrd1(TsThread::Cancel,Wym_ETHRDCAN,WyTimeSpec(1,0)); if((r=thrd1.begin())!=Ok) { WY_RETURN(r); } TsThread thrd2(TsThread::Return,Wym_EIO,TDelay); if((r=thrd2.begin())!=Ok) { WY_RETURN(r); } TsThread thrd3(TsThread::Exit,Wym_EINVAL,TDelay); if((r=thrd3.begin())!=Ok) { WY_RETURN(r); } return exaust_threads();};static const WyStr chdr( "+---------------+\n" "| main() caught:|\n" "+---------------+\n");int main(void) throw()try { WyRet r; Wy::cout << "Checking wy_thread.cpp, basic ...\n"; if(WyStr(Wy_Thread::class_name)!="Wy_Thread") { WY_THROW(WyRet() ); } #ifdef WY_DEBUG if(wy_created_cnt!=wy_joined_cnt) { WY_THROW( WyRet() ); } #endif chk_threadid(); // chk main thread id { const ::pthread_t SelfID=::pthread_self(); if(Wy_ThreadID::_thread_equal(Wy_Thread::wy_main_thrd_id,SelfID)==false) { WY_THROW( WyRet() ); } if(::pthread_equal(Wy_Thread::wy_main_thrd_id._pthread_id(),SelfID)==0) { WY_THROW( WyRet() ); } Wy::cout << "Wy::wrd(Wy_ThreadID())=\"" << Wy::wrd(Wy_ThreadID()) << "\"\n"; } // chk ck_thread_a() { if(Wy_Thread::active_threads()!=0) { WY_THROW( WyRet() ); } ck_thread_a(); if(Wy_Thread::active_threads()!=0) { Wy::cerr << "active_threads()=" << Wy_Thread::active_threads() << '\n'; WY_THROW( WyRet() ); } #ifdef WY_DEBUG if(wy_created_cnt!=wy_joined_cnt) { WY_THROW( WyRet() ); } #endif } // chk ck_thread_a() concurrently in different threads { const size_t Num_HThreads=20; HThread ht[Num_HThreads]; for(size_t i=0; i< Num_HThreads; ++i) { if((r=ht[i].begin())!=Ok) { WY_THROW(r); } if((r=ht[i].begin())!=Wym_EBADF) { WY_THROW(r); } } for(size_t i=0; i< Num_HThreads; ++i) { if((r=ht[i].wait_not(Wy_Thread::Active))!=Ok) { WY_THROW(r); } } if(Wy_Thread::active_threads()!=0) { WY_THROW( WyRet() ); } } // chk some static functions in non Wy_Thread created thread ck_thread_nwy(); // chk thread exausted r=exaust_threads(); if((r!=Wym_EAGAIN)&&(r!=Wym_ENOMEM) &&(r!=Wym_ENFILE) // on SUSE10 this can occur (g++ v4.03) ) { WY_THROW(r); } #ifdef WY_DEBUG if(wy_created_cnt!=wy_joined_cnt) { WY_THROW( WyRet() ); } Wy::cout << wy_created_cnt << " threads have been created\n"; // for now 125 is correct Wy::cout << wy_act_max << " maximal active threads\n"; #endif Wy::cout << "Checked Ok\n"; return(0);}catch(const WyRet& e) { Wy::cerr << chdr << Wy::wrd(e) << '\n'; return(-1);}catch(const std::exception& e) { Wy::cerr << chdr << "std::exception\n"; return(-1);}catch(...) { Wy::cerr << chdr << "unidentified stack unwound\n"; return(-1);};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -