📄 chk_mutex.cpp
字号:
/* Copyright is licensed under GNU LGPL. by I.J.Wang 2003 Note: No thread involved. This is basic check. Build: make chk_mutex*/#include "wymutex.h"#include <iostream>#include <cassert>#include <cstring>#include "wystr.h"#if WYMUTEX_VERSION!=31#error Test code is for WYMUTEX_VERSION 31#endif//// Test mutex throws as specificd// This test is common for all type of mutexes.//static void test_throw_error(void){ /* { try { WyMutex mtx; ::memset(&mtx,0,sizeof(mtx)); } catch(const WyMutex::Reply& e) { if(e.is_default()==false) { WY_THROW( WyRet() ); } goto t_exit; } catch(...) { throw; }; WY_THROW( WyRet() ); t_exit:; } { try { WyMutex mtx; ::memset(&mtx,0,sizeof(mtx)); throw WyReply(100); } catch(const WyMutex::Reply& e) { WY_THROW( WyRet(e) ); } catch(const WyReply& e) { if(e.c_errno()!=100) { WY_THROW( WyRet(e) ); } // FALLTHROUGH }; } */};//// Test mutex throws WyMutex::Reply as specificd (static version of functions)// This test is common for all type of mutexes.//static void test_throw_class_fault(void){ // // test lock(mtx) throw Reply(Wym_EDEADLK) // { WyMutex mtx(WyMutex::ErrorCheck); WyRet r=mtx.lock(); if(r!=Ok) { WY_THROW(r); } try { WyMutex::lock(mtx); // should throw Reply(Wym_EDEADLK) WyMutex::unlock(mtx); WY_THROW( WyRet() ); } catch(const WyMutex::Reply& e) { WyMutex::unlock(mtx); if(e!=Wym_EDEADLK) { WY_THROW( WyRet(e) ); } // FALL_THROUGH } catch(...) { WyMutex::unlock(mtx); throw; }; } // // test trylock(mtx) throw Reply(Wym_EDEADLK) // { WyMutex mtx; WyRet r=mtx.lock(); if(r!=Ok) { WY_THROW(r); } try { WyMutex::trylock(mtx); // should throw Reply(Wym_EBUSY) WyMutex::unlock(mtx); WY_THROW( WyRet() ); } catch(const WyMutex::Reply& e) { WyMutex::unlock(mtx); if(e!=Wym_EBUSY) { WY_THROW( WyRet(e) ); } } catch(...) { WyMutex::unlock(mtx); throw; }; } // // test unlock(mtx) throw Reply(Wym_EDEADLK) // { WyMutex mtx(WyMutex::ErrorCheck); try { WyMutex::unlock(mtx); // should throw Reply(Wym_EPERM) WY_THROW( WyRet() ); } catch(const WyMutex::Reply& e) { if(e!=Wym_EPERM) { WY_THROW( WyRet() ); } } }}static void test_fast_mutex(void){ WyRet r; WyMutex mtx(WyMutex::Fast); if((r=mtx.lock())!=Ok) { WY_THROW(r); } if((r=mtx.trylock())!=Wym_EBUSY) { WyMutex::unlock(mtx); WY_THROW(r); } if((r=mtx.unlock())!=Ok) { WY_THROW(r); } if((r=mtx.trylock())!=Ok) { WY_THROW(r); } if((r=mtx.unlock())!=Ok) { WY_THROW(r); } // // Unlock mutex twice was tested ok(fast mutex), keep this feature. // man. says 'always returns to the unlocked state' // // SIGSEGV encountered //if((r=mtx.unlock())!=Ok) { // WY_THROW(r); //} // static functions WyMutex::lock(mtx); WyMutex::unlock(mtx); WyMutex::trylock(mtx); WyMutex::unlock(mtx); //WyMutex::unlock(mtx); // see above unlock twice // chk mutex in the heap { WyMutex *pm= new WyMutex; if((r=pm->lock())!=Ok) { delete pm; WY_THROW(r); } if((r=pm->unlock())!=Ok) { delete pm; WY_THROW(r); } delete pm; }};static void test_recursive_mutex(void){ WyRet r; WyMutex mtx(WyMutex::Recursive); if((r=mtx.lock())!=Ok) { WY_THROW(r); } if((r=mtx.trylock())!=Ok) { // lock twice WyMutex::unlock(mtx); WY_THROW(r); } if((r=mtx.lock())!=Ok) { // lock thrice WyMutex::unlock(mtx); WY_THROW(r); } if((r=mtx.unlock())!=Ok) { WY_THROW(r); } if((r=mtx.unlock())!=Ok) { WY_THROW(r); } if((r=mtx.unlock())!=Ok) { WY_THROW(r); } // // Unlock mutex twice was tested to report Wym_EPERM(recursive mutex), // keep this feature for the test. // man. says 'always returns to the unlocked state' // if((r=mtx.unlock())!=Wym_EPERM) { WY_THROW(r); } // static functions WyMutex::lock(mtx); WyMutex::trylock(mtx); WyMutex::lock(mtx); WyMutex::unlock(mtx); WyMutex::unlock(mtx); // see above unlock twice WyMutex::unlock(mtx);};static void test_errcheck_mutex(void){ WyRet r; WyMutex mtx(WyMutex::ErrorCheck); if((r=mtx.lock())!=Ok) { WY_THROW(r); } if((r=mtx.trylock())!=Wym_EBUSY) { std::cerr << "\nError: trylock a locked mutex (ErrorCheck) returned:\n" << Wy::wrd(r).c_str() << " (this had been EBUSY). "; std::cerr << "\n Continue<y/n>?"; char ch; std::cin >> ch; if((ch!='y')&&(ch!='Y')) { WyMutex::unlock(mtx); WY_THROW(r); } } if((r=mtx.lock())!=Wym_EDEADLK) { WyMutex::unlock(mtx); WY_THROW(r); } if((r=mtx.unlock())!=Ok) { WY_THROW(r); } if((r=mtx.trylock())!=Ok) { WY_THROW(r); } if((r=mtx.unlock())!=Ok) { WY_THROW(r); } // // Unlock mutex twice was tested to report Wym_EPERM(errorcheck mutex), // keep this feature for the test. // man. says 'always returns to the unlocked state' // if((r=mtx.unlock())!=Wym_EPERM) { WY_THROW(r); } // static functions WyMutex::lock(mtx); WyMutex::unlock(mtx); WyMutex::trylock(mtx); WyMutex::unlock(mtx);};//// Test WyLock//static void test_WyLock(void){ WyRet r; WyMutex mtx; WyMutex mtx2; { WyMutex mtx(WyMutex::ErrorCheck); if((r=mtx.lock())!=Ok) { WY_THROW(r); } try { WyLock aa(mtx); // should throw Wym_EDEADLK WY_TERMINATE(""); } catch(const WyLock::Reply& e) { WyMutex::unlock(mtx); if(e!=Wym_EDEADLK) { WY_THROW( WyRet(e) ); } } catch(...) { WyMutex::unlock(mtx); throw; } } { // test destructor unlock WyLock aa(mtx); if((r=mtx.trylock())!=Wym_EBUSY) { WY_THROW(r); } } // aa should unlock mtx leaving the scope if((r=mtx.trylock())!=Ok) { WY_THROW(r); } if((r=mtx.unlock())!=Ok) { WY_THROW(r); } { // Test WyLock::xlock(..) WyLock aa(mtx); //if((r=aa.xlock(mtx))!=Ok) { // deadlock // WY_THROW(r); //} //if((r=aa.xlock(mtx))!=Wym_EDEADLK) { // WY_THROW(r); // xlock the same mutex //} if((r=mtx.trylock())!=Wym_EBUSY) { WY_THROW(r); // mtx did not locked } if((r=aa.xlock(mtx2))!=Ok) { WY_THROW(r); // transfer failed } if((r=mtx.trylock())!=Ok) { WY_THROW(r); // mtx should have unlocked } if((r=mtx.unlock())!=Ok) { WY_THROW(r); } if((r=mtx2.trylock())!=Wym_EBUSY) { WY_THROW(r); // WyLock::unlock failed } } // check mtx2 is unlocked // if((r=mtx2.trylock())!=Ok) { WY_THROW(r); // mtx should have unlocked } if((r=mtx2.unlock())!=Ok) { WY_THROW(r); } // // Test WyLock in a series of construct/and destruct // { for(int i=0; i<100; i++) try { WyLock aa(mtx); // transit to lock mtx2 if((r=aa.xlock(mtx2))!=Ok) { WY_THROW(r); } if((r=mtx2.trylock())!=Wym_EBUSY) { WY_THROW(r); } if((r=mtx.trylock())!=Ok) { WY_THROW(r); } if((r=mtx.unlock())!=Ok) { WY_THROW(r); } // transit to lock mtx if((r=aa.xlock(mtx))!=Ok) { WY_THROW(r); } if((r=mtx.trylock())!=Wym_EBUSY) { WY_THROW(r); } if((r=mtx2.trylock())!=Ok) { WY_THROW(r); } if((r=mtx2.unlock())!=Ok) { WY_THROW(r); } } catch(const WyRet& e) { std::cerr << Wy::wrd(e).c_str(); throw; }; } if((r=mtx.trylock())!=Ok) { WY_THROW(r); } if((r=mtx.unlock())!=Ok) { WY_THROW(r); }};static const WyStr chdr( "+---------------+\n" "| main() caught:|\n" "+---------------+\n");int main(void) throw()try { std::cout << "Checking WyMutex class (" __FILE__ ") ...\n"; if(WyStr(WyMutex::class_name)!="WyMutex") { WY_TERMINATE(""); } if(WyStr(WyLock::class_name)!="WyLock") { WY_TERMINATE(""); } std::cout << "sizeof(WyMutex)= " << sizeof(WyMutex) << '\n'; std::cout << "sizeof(WyLock)= " << sizeof(WyLock) << '\n'; test_fast_mutex(); test_recursive_mutex(); test_errcheck_mutex(); test_throw_error(); test_throw_class_fault(); test_WyLock(); std::cout << "Checked Ok\n"; return(0);}catch(const WyRet& e) { std::cerr << chdr.c_str() << Wy::wrd(e).c_str() << std::endl; return(-1);}catch(const std::exception& e) { std::cerr << chdr.c_str() << "std::exception" << std::endl; return(-1);}catch(...) { std::cerr << chdr.c_str() << "unknown unwind" << std::endl; return(-1);};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -