📄 test_ncbithr.cpp
字号:
// Cascaded R-lock must be allowed if (w_cycle % 10 == 0) { assert(m_RW->TryReadLock()); m_Res->BeginRead(m_Index); } // ======= CTls test ======= // Verify TLS - current value must be 10 assert(*m_Tls->GetValue() == 10); // Continue CRWLock test for (int i=0; i<7; i++) { delay(1); s_var++; } if (w_cycle % 4 == 0) { m_Res->EndWrite(m_Index); m_RW->Unlock(); } if (w_cycle % 6 == 0) { m_Res->EndRead(m_Index); m_RW->Unlock(); } if (w_cycle % 8 == 0) { m_Res->EndWrite(m_Index); m_RW->Unlock(); } if (w_cycle % 10 == 0) { m_Res->EndRead(m_Index); m_RW->Unlock(); } m_Res->EndWrite(m_Index); m_RW->Unlock(); delay(1); } } // ======= CTls test ======= // Verify TLS - current value must be 10 assert(*m_Tls->GetValue() == 10); for (int i=0; i<5; i++) { stored_value = new int; assert(stored_value != 0); *stored_value = *m_Tls->GetValue()+1; m_Tls->SetValue(stored_value, TestTlsCleanup, &m_CheckValue); assert(*stored_value == m_CheckValue+1); } assert(*m_Tls->GetValue() == 15); assert(m_CheckValue == 14); // ======= CThread::Detach() and CThread::Join() test ======= if (m_Index % 2 == 0) { CMutexGuard exit_guard(*exit_locks[m_Index]); delay(10); // Provide delay for join-before-exit } if (m_Index % 3 == 0) { // Never verified, since CThread::Exit() terminates the thread // inside Test_CThreadExit(). assert(Test_CThreadExit()); } return reinterpret_cast<void*>(-1);}/////////////////////////////////////////////////////////////////////////////// Test applicationclass CThreadedApp : public CNcbiApplication{ void Init(void); int Run(void);};void CThreadedApp::Init(void){ // Prepare command line descriptions auto_ptr<CArgDescriptions> arg_desc(new CArgDescriptions); // sNumThreads arg_desc->AddDefaultKey ("threads", "NumThreads", "Total number of threads to create and run", CArgDescriptions::eInteger, NStr::IntToString(sNumThreads)); arg_desc->SetConstraint ("threads", new CArgAllow_Integers(cNumThreadsMin, cNumThreadsMax)); // sSpawnBy arg_desc->AddDefaultKey ("spawnby", "SpawnBy", "Threads spawning factor", CArgDescriptions::eInteger, NStr::IntToString(sSpawnBy)); arg_desc->SetConstraint ("spawnby", new CArgAllow_Integers(cSpawnByMin, cSpawnByMax)); // sNumRCycles arg_desc->AddDefaultKey ("rcycles", "RCycles", "Number of read cycles by each reader thread", CArgDescriptions::eInteger, NStr::IntToString(sRCycles)); arg_desc->SetConstraint ("rcycles", new CArgAllow_Integers(cRCyclesMin, cRCyclesMax)); // sNumWCycles arg_desc->AddDefaultKey ("wcycles", "WCycles", "Number of write cycles by each writer thread", CArgDescriptions::eInteger, NStr::IntToString(sWCycles)); arg_desc->SetConstraint ("wcycles", new CArgAllow_Integers(cWCyclesMin, cWCyclesMax)); string prog_description = "This is a program testing thread, TLS, mutex and RW-lock classes."; arg_desc->SetUsageContext(GetArguments().GetProgramBasename(), prog_description, false); SetupArgDescriptions(arg_desc.release());}int CThreadedApp::Run(void){# if defined(NCBI_POSIX_THREADS) NcbiCout << "OS: Unix" << NcbiEndl;# elif defined(NCBI_WIN32_THREADS) NcbiCout << "OS: MS-Windows" << NcbiEndl;# else NcbiCout << "OS: unknown" << NcbiEndl;# endif // Process command line const CArgs& args = GetArgs(); sNumThreads = args["threads"].AsInteger(); sSpawnBy = args["spawnby"].AsInteger(); sRCycles = args["rcycles"].AsInteger(); sWCycles = args["wcycles"].AsInteger(); NcbiCout << "Test parameters:" << NcbiEndl; NcbiCout << "\tTotal threads " << sNumThreads << NcbiEndl; NcbiCout << "\tSpawn threads by " << sSpawnBy << NcbiEndl; NcbiCout << "\tR-cycles " << sRCycles << NcbiEndl; NcbiCout << "\tW-cycles " << sWCycles << NcbiEndl << NcbiEndl; // Redirect error log to hide messages sent by delay() SetDiagStream(0); // Test CBaseTls::Discard() NcbiCout << "Creating/discarding TLS test..."; int main_cleanup_flag = 0; CTls<int>* dummy_tls = new CTls<int>; assert(main_cleanup_flag == 0); dummy_tls->SetValue(&main_cleanup_flag, Main_Thread_Tls_Cleanup); assert(main_cleanup_flag == 0); dummy_tls->Discard(); assert(main_cleanup_flag == 1); NcbiCout << " Passed" << NcbiEndl << NcbiEndl; // Create test objects main_cleanup_flag = 0; CRef< CTls<int> > tls(new CTls<int>); tls->SetValue(0); CRWLock rw; CSharedResource res; {{ CFastMutexGuard guard(s_GlobalLock); NcbiCout << "===== Starting threads =====" << NcbiEndl; }} // Prepare exit-locks, lock each 2nd mutex // They will be used by join/detach before exit for (int i=0; i<sNumThreads; i++) { states[i] = eNull; exit_locks[i] = new CMutex; if (i % 2 == 0) { exit_locks[i]->Lock(); } } // Create and run threads for (int i=0; i<sSpawnBy; i++) { int idx; {{ CFastMutexGuard spawn_guard(s_GlobalLock); if (s_NextIndex >= sNumThreads) { break; } idx = s_NextIndex; s_NextIndex++; }} // Check Discard() for some threads if (i % 2 == 0) { thr[idx] = new CTestThread(idx, tls, &rw, &res); assert(states[idx] == eCreated); thr[idx]->Discard(); assert(states[idx] == eDestroyed); } thr[idx] = new CTestThread(idx, tls, &rw, &res); assert(states[idx] == eCreated); thr[idx]->Run(); {{ CFastMutexGuard guard(s_GlobalLock); NcbiCout << idx << " "; }} } // Wait for all threads running {{ CFastMutexGuard guard(s_GlobalLock); NcbiCout << NcbiEndl << NcbiEndl << "===== Waiting for all threads to run =====" << NcbiEndl; }} map<int, bool> thread_map; for (int i=0; i<sNumThreads; i++) { thread_map[i] = false; } int ready = 0; while (ready < sNumThreads) { ready = 0; for (int i=0; i<sNumThreads; i++) { if (states[i] >= eRunning) { ready++; if ( !thread_map[i] ) { CFastMutexGuard guard(s_GlobalLock); NcbiCout << i << " "; thread_map[i] = true; } } } } {{ CFastMutexGuard guard(s_GlobalLock); NcbiCout << NcbiEndl << NcbiEndl << "===== Joining threads before exit =====" << NcbiEndl; }} for (int i=0; i<sNumThreads; i++) { // Try to join before exit if (i % 4 == 2) { assert(states[i] < eTerminated); exit_locks[i]->Unlock(); void* exit_data = 0; thr[i]->Join(&exit_data); // Must be set to 1 by Main() assert(exit_data != 0); {{ CFastMutexGuard guard(s_GlobalLock); NcbiCout << i << " "; }} } } // Reset CRef to the test tls. One more CRef to the object // must have been stored in the CThread's m_UsedTlsSet. assert(main_cleanup_flag == 0); tls.Reset(); assert(main_cleanup_flag == 0); {{ CFastMutexGuard guard(s_GlobalLock); NcbiCout << NcbiEndl << NcbiEndl << "===== Detaching threads before exit =====" << NcbiEndl; }} for (int i=0; i<sNumThreads; i++) { // Detach before exit if (i % 4 == 0) { assert(states[i] < eTerminated); thr[i]->Detach(); exit_locks[i]->Unlock(); {{ CFastMutexGuard guard(s_GlobalLock); NcbiCout << i << " "; }} } } // Wait for all threads to exit delay(10); {{ CFastMutexGuard guard(s_GlobalLock); NcbiCout << NcbiEndl << NcbiEndl << "===== Detaching threads after exit =====" << NcbiEndl; }} for (int i=0; i<sNumThreads; i++) { // Detach after exit if (i % 4 == 1) { assert(states[i] != eDestroyed); thr[i]->Detach(); {{ CFastMutexGuard guard(s_GlobalLock); NcbiCout << i << " "; }} } } {{ CFastMutexGuard guard(s_GlobalLock); NcbiCout << NcbiEndl << NcbiEndl << "===== Joining threads after exit =====" << NcbiEndl; }} for (int i=0; i<sNumThreads; i++) { // Join after exit if (i % 4 == 3) { assert(states[i] != eDestroyed); thr[i]->Join(); {{ CFastMutexGuard guard(s_GlobalLock); NcbiCout << i << " "; }} } } // Wait for all threads to be destroyed {{ CFastMutexGuard guard(s_GlobalLock); NcbiCout << NcbiEndl << NcbiEndl << "===== Waiting for all threads to be destroyed =====" << NcbiEndl; }} for (int i=0; i<sNumThreads; i++) { thread_map[i] = false; } ready = 0; while (ready < sNumThreads) { ready = 0; for (int i=0; i<sNumThreads; i++) { if (states[i] == eDestroyed) { ready++; if ( !thread_map[i] ) { CFastMutexGuard guard(s_GlobalLock); NcbiCout << i << " "; thread_map[i] = true; delete exit_locks[i]; } } } } {{ CFastMutexGuard guard(s_GlobalLock); NcbiCout << NcbiEndl << NcbiEndl << "Test passed" << NcbiEndl; }} return 0;}/////////////////////////////////////////////////////////////////////////////// MAINint main(int argc, const char* argv[]) { CThreadedApp app; return app.AppMain(argc, argv, 0, eDS_Default, 0);}/* * =========================================================================== * $Log: test_ncbithr.cpp,v $ * Revision 1000.1 2004/06/01 19:10:21 gouriano * PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R6.7 * * Revision 6.7 2004/05/14 13:59:51 gorelenk * Added include of ncbi_pch.hpp * * Revision 6.6 2002/11/04 21:29:05 grichenk * Fixed usage of const CRef<> and CRef<> constructor * * Revision 6.5 2002/09/19 20:05:43 vasilche * Safe initialization of static mutexes * * Revision 6.4 2002/04/16 18:49:09 ivanov * Centralize threatment of assert() in tests. * Added #include <test/test_assert.h>. CVS log moved to end of file. * * Revision 6.3 2002/03/13 05:02:09 vakatov * sNumThreads = 35; sSpawnBy = 6; * * Revision 6.2 2001/04/03 18:21:23 grichenk * + test for CThread::Exit() * * Revision 6.1 2001/03/13 22:45:20 vakatov * Initial revision * * =========================================================================== */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -