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

📄 test_ncbithr.cpp

📁 ncbi源码
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/* * =========================================================================== * PRODUCTION $Log: test_ncbithr.cpp,v $ * PRODUCTION Revision 1000.1  2004/06/01 19:10:21  gouriano * PRODUCTION PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R6.7 * PRODUCTION * =========================================================================== *//*  $Id: test_ncbithr.cpp,v 1000.1 2004/06/01 19:10:21 gouriano Exp $ * =========================================================================== * *                            PUBLIC DOMAIN NOTICE *               National Center for Biotechnology Information * *  This software/database is a "United States Government Work" under the *  terms of the United States Copyright Act.  It was written as part of *  the author's official duties as a United States Government employee and *  thus cannot be copyrighted.  This software/database is freely available *  to the public for use. The National Library of Medicine and the U.S. *  Government have not placed any restriction on its use or reproduction. * *  Although all reasonable efforts have been taken to ensure the accuracy *  and reliability of the software and data, the NLM and the U.S. *  Government do not and cannot warrant the performance or results that *  may be obtained by using this software or data. The NLM and the U.S. *  Government disclaim all warranties, express or implied, including *  warranties of performance, merchantability or fitness for any particular *  purpose. * *  Please cite the author in any work or product based on this material. * * =========================================================================== * * Author:  Aleksey Grichenko * * File Description: *   Test for multithreading classes * */#include <ncbi_pch.hpp>#include <corelib/ncbistd.hpp>#include <corelib/ncbiapp.hpp>#include <corelib/ncbithr.hpp>#include <corelib/ncbimtx.hpp>#include <corelib/ncbienv.hpp>#include <corelib/ncbiargs.hpp>#include <corelib/ncbidiag.hpp>#include <map>#include <test/test_assert.h>  /* This header must go last */USING_NCBI_SCOPE;/////////////////////////////////////////////////////////////////////////////// Globalsconst int   cNumThreadsMin = 1;const int   cNumThreadsMax = 500;const int   cSpawnByMin    = 1;const int   cSpawnByMax    = 100;const int   cRCyclesMin    = 10;const int   cRCyclesMax    = 5000;const int   cWCyclesMin    = 5;const int   cWCyclesMax    = 1000;static int  sNumThreads    = 35;static int  sSpawnBy       = 6;static int  sRCycles       = 100;static int  sWCycles       = 50;static int  s_NextIndex    = 0;DEFINE_STATIC_FAST_MUTEX(s_GlobalLock);void delay(int value){    for (int i=0; i<value; i++) {        CFastMutexGuard out_guard(s_GlobalLock);    }}void TestTlsCleanup(int* p_value, void* p_ref){    // Copy current value, then delete it    *static_cast<int*>(p_ref) = *p_value;    delete p_value;}void Main_Thread_Tls_Cleanup(int* p_value, void* /* p_data */){    (*p_value)++;}/////////////////////////////////////////////////////////////////////////////// Shared resource imitation////   Imitates reading & writing of a shared resource.//   Checks if there are violations of read-write locks.//class CSharedResource{public:    CSharedResource(void) : m_Readers(0),                            m_Writer(-1) {}    ~CSharedResource(void) { assert(!m_Readers); }    void BeginRead(int ID);    void BeginWrite(int ID);    void EndRead(int ID);    void EndWrite(int ID);private:    int m_Readers;    int m_Writer;    CFastMutex m_Mutex;};void CSharedResource::BeginRead(int ID){    CFastMutexGuard guard(m_Mutex);    // Must be unlocked, R-locked, or W-locked by the same thread    assert(m_Readers >= 0 || (m_Readers < 0 && ID == m_Writer));    (m_Readers >= 0) ? m_Readers++ : m_Readers--;}void CSharedResource::BeginWrite(int ID){    CFastMutexGuard guard(m_Mutex);    // Must be unlocked or W-locked by the same thread    assert(m_Readers == 0 || (m_Readers < 0 && ID == m_Writer));    m_Readers--;    m_Writer = ID;}void CSharedResource::EndRead(int ID){    CFastMutexGuard guard(m_Mutex);    // Must be R-locked or W-locked by the same thread    assert(m_Readers > 0 || (m_Readers < 0 && m_Writer == ID));    (m_Readers > 0) ? m_Readers-- : m_Readers++;    if (m_Readers == 0) {        m_Writer = -1;    }}void CSharedResource::EndWrite(int ID){    CFastMutexGuard guard(m_Mutex);    // Must be W-locked by the same thread;    assert(m_Readers < 0 && m_Writer == ID);    m_Readers++;    if (m_Readers == 0) {        m_Writer = -1;    }}/////////////////////////////////////////////////////////////////////////////// Test threadclass CTestThread : public CThread{public:    CTestThread(int index, CTls<int>* tls, CRWLock* rw, CSharedResource* res);protected:    ~CTestThread(void);    virtual void* Main(void);    virtual void  OnExit(void);private:    int              m_Index;        // Thread sequential index    CTls<int>*       m_Tls;          // Test TLS object    int              m_CheckValue;   // Value to compare with the TLS data    CRWLock*         m_RW;           // Test RWLock object    CSharedResource* m_Res;         // Shared resource imitation};// Thread states checked by the main threadenum   TTestThreadState {    eNull,          // Initial value    eCreated,       // Set by CTestThread::CTestThread()    eRunning,       // Set by CTestThread::Main()    eTerminated,    // Set by CTestThread::OnExit()    eDestroyed      // Set by CTestThread::~CTestThread()};// Pointers to all threads and corresponding statesCTestThread*        thr[cNumThreadsMax];TTestThreadState    states[cNumThreadsMax];// Prevent threads from termination before Detach() or Join()CMutex*             exit_locks[cNumThreadsMax];CTestThread::CTestThread(int index,                         CTls<int>* tls,                         CRWLock* rw,                         CSharedResource* res)    : m_Index(index),      m_Tls(tls),      m_CheckValue(15),      m_RW(rw),      m_Res(res){    CFastMutexGuard guard(s_GlobalLock);    states[m_Index] = eCreated;}CTestThread::~CTestThread(void){    CFastMutexGuard guard(s_GlobalLock);    assert(m_CheckValue == 15);    states[m_Index] = eDestroyed;}void CTestThread::OnExit(void){    CFastMutexGuard guard(s_GlobalLock);    states[m_Index] = eTerminated;}bool Test_CThreadExit(void){    DEFINE_STATIC_FAST_MUTEX(s_Exit_Mutex);    CFastMutexGuard guard(s_Exit_Mutex);    // The mutex must be unlocked after call to CThread::Exit()    try {        CThread::Exit(reinterpret_cast<void*>(-1));    }    catch (...) {        throw;    }    return false;   // this line should never be executed}void* CTestThread::Main(void){    {{        CFastMutexGuard guard(s_GlobalLock);        states[m_Index] = eRunning;    }}    // ======= CTls test =======    // Verify TLS - initial value must be 0    m_CheckValue = 0;    assert(m_Tls->GetValue() == 0);    int* stored_value = new int;    assert(stored_value != 0);    *stored_value = 0;    m_Tls->SetValue(stored_value, TestTlsCleanup, &m_CheckValue);    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);    }    // ======= CThread test =======    for (int i = 0; i<sSpawnBy; i++) {        int idx;        {{            CFastMutexGuard spawn_guard(s_GlobalLock);            if (s_NextIndex >= sNumThreads) {                break;            }            idx = s_NextIndex;            s_NextIndex++;        }}        thr[idx] = new CTestThread(idx, m_Tls, m_RW, m_Res);        assert(states[idx] == eCreated);        thr[idx]->Run();        {{            CFastMutexGuard guard(s_GlobalLock);            NcbiCout << idx << " ";        }}    }    // ======= CTls test =======    // Verify TLS - current value must be 5    assert(*m_Tls->GetValue() == 5);    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);    }    // ======= CRWLock test =======    static int s_var = 0; // global value    if (m_Index % 5) {         // <------ Reader        for (int r_cycle=0; r_cycle<sRCycles*2; r_cycle++) {            // Lock immediately or wait for locking            if (!m_RW->TryReadLock()) {                m_RW->ReadLock();            }            int l_var = s_var;    // must remain the same while R-locked                        m_Res->BeginRead(m_Index);            assert(l_var == s_var);            // Cascaded R-lock            if (r_cycle % 6 == 0) {                m_RW->ReadLock();                m_Res->BeginRead(m_Index);            }            assert(l_var == s_var);            // Cascaded R-lock must be allowed            if (r_cycle % 12 == 0) {                assert(m_RW->TryReadLock());                m_Res->BeginRead(m_Index);                m_Res->EndRead(m_Index);                m_RW->Unlock();	    }            // W-after-R must be prohibited            assert( !m_RW->TryWriteLock() );            delay(10);            // ======= CTls test =======            // Verify TLS - current value must be 10            assert(*m_Tls->GetValue() == 10);            assert(l_var == s_var);            // Cascaded R-lock must be allowed            if (r_cycle % 7 == 0) {                assert(m_RW->TryReadLock());                m_Res->BeginRead(m_Index);                m_Res->EndRead(m_Index);                m_RW->Unlock();            }            assert(l_var == s_var);            if (r_cycle % 6 == 0) {                m_Res->EndRead(m_Index);                m_RW->Unlock();            }            assert(l_var == s_var);            m_Res->EndRead(m_Index);            m_RW->Unlock();        }    }    else {                     // <------ Writer        for (int w_cycle=0; w_cycle<sWCycles; w_cycle++) {            // Lock immediately or wait for locking            if (!m_RW->TryWriteLock()) {                m_RW->WriteLock();            }            m_Res->BeginWrite(m_Index);            // Cascaded W-lock            if (w_cycle % 4 == 0) {                m_RW->WriteLock();                m_Res->BeginWrite(m_Index);            }            // R-after-W (treated as cascaded W-lock)            if (w_cycle % 6 == 0) {                m_RW->ReadLock();                m_Res->BeginRead(m_Index);            }            // Cascaded W-lock must be allowed            if (w_cycle % 8 == 0) {                assert(m_RW->TryWriteLock());                m_Res->BeginWrite(m_Index);            }

⌨️ 快捷键说明

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