ncbithr.cpp
上传用户:yhdzpy8989
上传日期:2007-06-13
资源大小:13604k
文件大小:21k
源码类别:

生物技术

开发平台:

C/C++

  1. /*
  2.  * ===========================================================================
  3.  * PRODUCTION $Log: ncbithr.cpp,v $
  4.  * PRODUCTION Revision 1000.1  2004/06/01 19:09:26  gouriano
  5.  * PRODUCTION PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.30
  6.  * PRODUCTION
  7.  * ===========================================================================
  8.  */
  9. /*  $Id: ncbithr.cpp,v 1000.1 2004/06/01 19:09:26 gouriano Exp $
  10.  * ===========================================================================
  11.  *
  12.  *                            PUBLIC DOMAIN NOTICE
  13.  *               National Center for Biotechnology Information
  14.  *
  15.  *  This software/database is a "United States Government Work" under the
  16.  *  terms of the United States Copyright Act.  It was written as part of
  17.  *  the author's official duties as a United States Government employee and
  18.  *  thus cannot be copyrighted.  This software/database is freely available
  19.  *  to the public for use. The National Library of Medicine and the U.S.
  20.  *  Government have not placed any restriction on its use or reproduction.
  21.  *
  22.  *  Although all reasonable efforts have been taken to ensure the accuracy
  23.  *  and reliability of the software and data, the NLM and the U.S.
  24.  *  Government do not and cannot warrant the performance or results that
  25.  *  may be obtained by using this software or data. The NLM and the U.S.
  26.  *  Government disclaim all warranties, express or implied, including
  27.  *  warranties of performance, merchantability or fitness for any particular
  28.  *  purpose.
  29.  *
  30.  *  Please cite the author in any work or product based on this material.
  31.  *
  32.  * ===========================================================================
  33.  *
  34.  * Author:  Denis Vakatov, Aleksey Grichenko
  35.  *
  36.  * File Description:
  37.  *   Multi-threading -- classes, functions, and features.
  38.  *
  39.  *    TLS:
  40.  *      CTlsBase         -- TLS implementation (base class for CTls<>)
  41.  *
  42.  *    THREAD:
  43.  *      CThread          -- thread wrapper class
  44.  *
  45.  *    RW-LOCK:
  46.  *      CInternalRWLock  -- platform-dependent RW-lock structure (fwd-decl)
  47.  *      CRWLock          -- Read/Write lock related  data and methods
  48.  *
  49.  */
  50. #include <ncbi_pch.hpp>
  51. #include <corelib/ncbithr.hpp>
  52. #include <corelib/ncbimtx.hpp>
  53. #include <corelib/ncbi_safe_static.hpp>
  54. #include <corelib/ncbi_limits.h>
  55. #include <corelib/ncbi_system.hpp>
  56. #include <assert.h>
  57. #ifdef NCBI_POSIX_THREADS
  58. #  include <sys/time.h> // for gettimeofday()
  59. #endif
  60. #include "ncbidbg_p.hpp"
  61. BEGIN_NCBI_SCOPE
  62. /////////////////////////////////////////////////////////////////////////////
  63. //  CTlsBase::
  64. //
  65. // Flag and function to report s_Tls_TlsSet destruction
  66. static bool s_TlsSetDestroyed = false;
  67. static void s_TlsSetCleanup(void* /* ptr */)
  68. {
  69.     s_TlsSetDestroyed = true;
  70. }
  71. // Set of all TLS objects -- to prevent memory leaks due to
  72. // undestroyed TLS objects, and to avoid premature TLS destruction.
  73. typedef set< CRef<CTlsBase> > TTls_TlsSet;
  74. static CSafeStaticPtr<TTls_TlsSet> s_Tls_TlsSet(s_TlsSetCleanup);
  75. // Protects "s_Tls_TlsSet"
  76. struct S {
  77.     DECLARE_CLASS_STATIC_FAST_MUTEX(s_TlsMutex0);
  78. };
  79. DEFINE_CLASS_STATIC_FAST_MUTEX(S::s_TlsMutex0);
  80. #define s_TlsMutex S::s_TlsMutex0
  81. CTlsBase::CTlsBase(void)
  82. {
  83.     DoDeleteThisObject();
  84.     // Create platform-dependent TLS key (index)
  85. #if defined(NCBI_WIN32_THREADS)
  86.     xncbi_Verify((m_Key = TlsAlloc()) != DWORD(-1));
  87. #elif defined(NCBI_POSIX_THREADS)
  88.     xncbi_Verify(pthread_key_create(&m_Key, 0) == 0);
  89. #else
  90.     m_Key = 0;
  91. #endif
  92.     m_Initialized = true;
  93.     // Add to the cleanup set if it still exists
  94.     if ( !s_TlsSetDestroyed ) {
  95.         CFastMutexGuard guard(s_TlsMutex);
  96.         s_Tls_TlsSet->insert(CRef<CTlsBase> (this));
  97.     }
  98. }
  99. CTlsBase::~CTlsBase(void)
  100. {
  101.     x_Reset();
  102.     m_Initialized = false;
  103.     // Destroy system TLS key
  104. #if defined(NCBI_WIN32_THREADS)
  105.     if ( TlsFree(m_Key) ) {
  106.         m_Key = 0;
  107.         return;
  108.     }
  109.     assert(0);
  110. #elif defined(NCBI_POSIX_THREADS)
  111.     if (pthread_key_delete(m_Key) == 0) {
  112.         m_Key = 0;
  113.         return;
  114.     }
  115.     assert(0);
  116. #else
  117.     m_Key = 0;
  118.     return;
  119. #endif
  120. }
  121. void CTlsBase::x_Discard(void)
  122. {
  123.     if ( s_TlsSetDestroyed ) {
  124.         return;  // Nothing to do - the TLS set has been destroyed
  125.     }
  126.     CFastMutexGuard guard(s_TlsMutex);
  127.     NON_CONST_ITERATE(TTls_TlsSet, it, *s_Tls_TlsSet) {
  128.         if (it->GetPointer() == this) {
  129.             s_Tls_TlsSet->erase(it);
  130.             break;
  131.         }
  132.     }
  133. }
  134. // Platform-specific TLS data storing
  135. inline
  136. void s_TlsSetValue(TTlsKey& key, void* data, const char* err_message)
  137. {
  138. #if defined(NCBI_WIN32_THREADS)
  139.     xncbi_Validate(TlsSetValue(key, data), err_message);
  140. #elif defined(NCBI_POSIX_THREADS)
  141.     xncbi_Validate(pthread_setspecific(key, data) == 0, err_message);
  142. #else
  143.     key = data;
  144.     assert(err_message);  // to get rid of the "unused variable" warning
  145. #endif
  146. }
  147. void CTlsBase::x_SetValue(void*        value,
  148.                           FCleanupBase cleanup,
  149.                           void*        cleanup_data)
  150. {
  151.     if ( !m_Initialized ) {
  152.         return;
  153.     }
  154.     // Get previously stored data
  155.     STlsData* tls_data = static_cast<STlsData*> (x_GetTlsData());
  156.     // Create and initialize TLS structure, if it was not present
  157.     if ( !tls_data ) {
  158.         tls_data = new STlsData;
  159.         xncbi_Validate(tls_data != 0,
  160.                        "CTlsBase::x_SetValue() -- cannot allocate "
  161.                        "memory for TLS data");
  162.         tls_data->m_Value       = 0;
  163.         tls_data->m_CleanupFunc = 0;
  164.         tls_data->m_CleanupData = 0;
  165.     }
  166.     // Cleanup
  167.     if (tls_data->m_CleanupFunc  &&  tls_data->m_Value != value) {
  168.         tls_data->m_CleanupFunc(tls_data->m_Value, tls_data->m_CleanupData);
  169.     }
  170.     // Store the values
  171.     tls_data->m_Value       = value;
  172.     tls_data->m_CleanupFunc = cleanup;
  173.     tls_data->m_CleanupData = cleanup_data;
  174.     // Store the structure in the TLS
  175.     s_TlsSetValue(m_Key, tls_data,
  176.                   "CTlsBase::x_SetValue() -- error setting value");
  177.     // Add to the used TLS list to cleanup data in the thread Exit()
  178.     CThread::AddUsedTls(this);
  179. }
  180. void CTlsBase::x_Reset(void)
  181. {
  182.     if ( !m_Initialized ) {
  183.         return;
  184.     }
  185.     // Get previously stored data
  186.     STlsData* tls_data = static_cast<STlsData*> (x_GetTlsData());
  187.     if ( !tls_data ) {
  188.         return;
  189.     }
  190.     // Cleanup & destroy
  191.     if ( tls_data->m_CleanupFunc ) {
  192.         tls_data->m_CleanupFunc(tls_data->m_Value, tls_data->m_CleanupData);
  193.     }
  194.     delete tls_data;
  195.     // Store NULL in the TLS
  196.     s_TlsSetValue(m_Key, 0,
  197.                   "CTlsBase::x_Reset() -- error cleaning-up TLS");
  198. }
  199. /////////////////////////////////////////////////////////////////////////////
  200. //  CExitThreadException::
  201. //
  202. //    Exception used to terminate threads safely, cleaning up
  203. //    all the resources allocated.
  204. //
  205. class CExitThreadException
  206. {
  207. public:
  208.     // Create new exception object, initialize counter.
  209.     CExitThreadException(void);
  210.     // Create a copy of exception object, increase counter.
  211.     CExitThreadException(const CExitThreadException& prev);
  212.     // Destroy the object, decrease counter. If the counter is
  213.     // zero outside of CThread::Wrapper(), rethrow exception.
  214.     ~CExitThreadException(void);
  215.     // Inform the object it has reached CThread::Wrapper().
  216.     void EnterWrapper(void)
  217.     {
  218.         *m_InWrapper = true;
  219.     }
  220. private:
  221.     int* m_RefCount;
  222.     bool* m_InWrapper;
  223. };
  224. CExitThreadException::CExitThreadException(void)
  225.     : m_RefCount(new int),
  226.       m_InWrapper(new bool)
  227. {
  228.     *m_RefCount = 1;
  229.     *m_InWrapper = false;
  230. }
  231. CExitThreadException::CExitThreadException(const CExitThreadException& prev)
  232.     : m_RefCount(prev.m_RefCount),
  233.       m_InWrapper(prev.m_InWrapper)
  234. {
  235.     (*m_RefCount)++;
  236. }
  237. CExitThreadException::~CExitThreadException(void)
  238. {
  239.     if (--(*m_RefCount) > 0) {
  240.         // Not the last object - continue to handle exceptions
  241.         return;
  242.     }
  243.     bool tmp_in_wrapper = *m_InWrapper; // save the flag
  244.     delete m_RefCount;
  245.     delete m_InWrapper;
  246.     if ( !tmp_in_wrapper ) {
  247.         // Something is wrong - terminate the thread
  248.         assert(((void)("CThread::Exit() -- cannot exit thread"), 0));
  249. #if defined(NCBI_WIN32_THREADS)
  250.         ExitThread(0);
  251. #elif defined(NCBI_POSIX_THREADS)
  252.         pthread_exit(0);
  253. #endif
  254.     }
  255. }
  256. /////////////////////////////////////////////////////////////////////////////
  257. //  CThread::
  258. //
  259. // Mutex to protect CThread members and to make sure that Wrapper() function
  260. // will not proceed until after the appropriate Run() is finished.
  261. DEFINE_STATIC_FAST_MUTEX(s_ThreadMutex);
  262. DEFINE_STATIC_FAST_MUTEX(s_TlsCleanupMutex);
  263. // Internal storage for thread objects and related variables/functions
  264. CTls<CThread>* CThread::sm_ThreadsTls;
  265. void s_CleanupThreadsTls(void* /* ptr */)
  266. {
  267.     CThread::sm_ThreadsTls = 0;  // Indicate that the TLS is destroyed
  268. }
  269. void CThread::CreateThreadsTls(void)
  270. {
  271.     static CSafeStaticRef< CTls<CThread> >
  272.         s_ThreadsTlsRef(s_CleanupThreadsTls);
  273.     sm_ThreadsTls = &s_ThreadsTlsRef.Get();
  274. }
  275. TWrapperRes CThread::Wrapper(TWrapperArg arg)
  276. {
  277.     // Get thread object and self ID
  278.     CThread* thread_obj = static_cast<CThread*>(arg);
  279.     // Set Toolkit thread ID. Otherwise no mutexes will work!
  280.     {{
  281.         CFastMutexGuard guard(s_ThreadMutex);
  282.         static int s_ThreadCount = 0;
  283.         s_ThreadCount++;
  284.         thread_obj->m_ID = s_ThreadCount;
  285.         xncbi_Validate(thread_obj->m_ID != 0,
  286.                        "CThread::Wrapper() -- error assigning thread ID");
  287.         GetThreadsTls().SetValue(thread_obj);
  288.     }}
  289.     // Run user-provided thread main function here
  290.     try {
  291.         thread_obj->m_ExitData = thread_obj->Main();
  292.     }
  293.     catch (CExitThreadException& e) {
  294.         e.EnterWrapper();
  295.     }
  296.     STD_CATCH_ALL("CThread::Wrapper: CThread::Main() failed");
  297.     // Call user-provided OnExit()
  298.     try {
  299.         thread_obj->OnExit();
  300.     }
  301.     STD_CATCH_ALL("CThread::Wrapper: CThread::OnExit() failed");
  302.     // Cleanup local storages used by this thread
  303.     {{
  304.         CFastMutexGuard tls_cleanup_guard(s_TlsCleanupMutex);
  305.         NON_CONST_ITERATE(TTlsSet, it, thread_obj->m_UsedTls) {
  306.             CRef<CTlsBase> tls = *it;
  307.             tls->x_Reset();
  308.         }
  309.     }}
  310.     {{
  311.         CFastMutexGuard state_guard(s_ThreadMutex);
  312.         // Indicate the thread is terminated
  313.         thread_obj->m_IsTerminated = true;
  314.         // Schedule the thread object for destruction, if detached
  315.         if ( thread_obj->m_IsDetached ) {
  316.             thread_obj->m_SelfRef.Reset();
  317.         }
  318.     }}
  319.     return 0;
  320. }
  321. CThread::CThread(void)
  322.     : m_IsRun(false),
  323.       m_IsDetached(false),
  324.       m_IsJoined(false),
  325.       m_IsTerminated(false),
  326.       m_ExitData(0)
  327. {
  328.     DoDeleteThisObject();
  329. #if defined(HAVE_PTHREAD_SETCONCURRENCY)  &&  defined(NCBI_POSIX_THREADS)
  330.     // Adjust concurrency for Solaris etc.
  331.     if (pthread_getconcurrency() == 0) {
  332.         xncbi_Validate(pthread_setconcurrency(GetCpuCount()) == 0,
  333.                        "CThread::CThread() -- pthread_setconcurrency(2) "
  334.                        "failed");
  335.     }
  336. #endif
  337. }
  338. CThread::~CThread(void)
  339. {
  340. #if defined(NCBI_WIN32_THREADS)
  341.     // close handle if it's not yet closed
  342.     CFastMutexGuard state_guard(s_ThreadMutex);
  343.     if ( m_IsRun && m_Handle != NULL ) {
  344.         CloseHandle(m_Handle);
  345.         m_Handle = NULL;
  346.     }
  347. #endif
  348. }
  349. #if defined(NCBI_POSIX_THREADS)
  350. extern "C" {
  351.     typedef TWrapperRes (*FSystemWrapper)(TWrapperArg);
  352. }
  353. #elif defined(NCBI_WIN32_THREADS)
  354. extern "C" {
  355.     typedef TWrapperRes (WINAPI *FSystemWrapper)(TWrapperArg);
  356. }
  357. #endif
  358. bool CThread::Run(TRunMode flags)
  359. {
  360.     // Do not allow the new thread to run until m_Handle is set
  361.     CFastMutexGuard state_guard(s_ThreadMutex);
  362.     // Check
  363.     xncbi_Validate(!m_IsRun,
  364.                    "CThread::Run() -- called for already started thread");
  365.     m_IsDetached = (flags & fRunDetached) != 0;
  366. #if defined(NCBI_WIN32_THREADS)
  367.     // We need this parameter in WinNT - can not use NULL instead!
  368.     DWORD  thread_id;
  369.     m_Handle = CreateThread(NULL, 0,
  370.                             reinterpret_cast<FSystemWrapper>(Wrapper),
  371.                             this, 0, &thread_id);
  372.     xncbi_Validate(m_Handle != NULL,
  373.                    "CThread::Run() -- error creating thread");
  374.     if ( m_IsDetached ) {
  375.         CloseHandle(m_Handle);
  376.         m_Handle = NULL;
  377.     }
  378.     else {
  379.         // duplicate handle to adjust security attributes
  380.         HANDLE oldHandle = m_Handle;
  381.         xncbi_Validate(DuplicateHandle(GetCurrentProcess(), oldHandle,
  382.                                        GetCurrentProcess(), &m_Handle,
  383.                                        0, FALSE, DUPLICATE_SAME_ACCESS),
  384.                        "CThread::Run() -- error getting thread handle");
  385.         xncbi_Validate(CloseHandle(oldHandle),
  386.                        "CThread::Run() -- error closing thread handle");
  387.     }
  388. #elif defined(NCBI_POSIX_THREADS)
  389.     pthread_attr_t attr;
  390.     xncbi_Validate(pthread_attr_init (&attr) == 0,
  391.                    "CThread::Run() - error initializing thread attributes");
  392.     if ( ! (flags & fRunUnbound) ) {
  393.         xncbi_Validate(pthread_attr_setscope(&attr,
  394.                                              PTHREAD_SCOPE_SYSTEM) == 0,
  395.                        "CThread::Run() - error setting thread scope");
  396.     }
  397.     if ( m_IsDetached ) {
  398.         xncbi_Validate(pthread_attr_setdetachstate(&attr,
  399.                                                    PTHREAD_CREATE_DETACHED) == 0,
  400.                        "CThread::Run() - error setting thread detach state");
  401.     }
  402.     xncbi_Validate(pthread_create(&m_Handle, &attr,
  403.                                   reinterpret_cast<FSystemWrapper>(Wrapper),
  404.                                   this) == 0,
  405.                    "CThread::Run() -- error creating thread");
  406.     xncbi_Validate(pthread_attr_destroy(&attr) == 0,
  407.                    "CThread::Run() - error destroying thread attributes");
  408. #else
  409.     if (flags & fRunAllowST) {
  410.         Wrapper(this);
  411.     }
  412.     else {
  413.         xncbi_Validate(0,
  414.                        "CThread::Run() -- system does not support threads");
  415.     }
  416. #endif
  417.     // prevent deletion of CThread until thread is finished
  418.     m_SelfRef.Reset(this);
  419.     // Indicate that the thread is run
  420.     m_IsRun = true;
  421.     return true;
  422. }
  423. void CThread::Detach(void)
  424. {
  425.     CFastMutexGuard state_guard(s_ThreadMutex);
  426.     // Check the thread state: it must be run, but not detached yet
  427.     xncbi_Validate(m_IsRun,
  428.                    "CThread::Detach() -- called for not yet started thread");
  429.     xncbi_Validate(!m_IsDetached,
  430.                    "CThread::Detach() -- called for already detached thread");
  431.     // Detach the thread
  432. #if defined(NCBI_WIN32_THREADS)
  433.     xncbi_Validate(CloseHandle(m_Handle),
  434.                    "CThread::Detach() -- error closing thread handle");
  435.     m_Handle = NULL;
  436. #elif defined(NCBI_POSIX_THREADS)
  437.     xncbi_Validate(pthread_detach(m_Handle) == 0,
  438.                    "CThread::Detach() -- error detaching thread");
  439. #endif
  440.     // Indicate the thread is detached
  441.     m_IsDetached = true;
  442.     // Schedule the thread object for destruction, if already terminated
  443.     if ( m_IsTerminated ) {
  444.         m_SelfRef.Reset();
  445.     }
  446. }
  447. void CThread::Join(void** exit_data)
  448. {
  449.     // Check the thread state: it must be run, but not detached yet
  450.     {{
  451.         CFastMutexGuard state_guard(s_ThreadMutex);
  452.         xncbi_Validate(m_IsRun,
  453.                        "CThread::Join() -- called for not yet started thread");
  454.         xncbi_Validate(!m_IsDetached,
  455.                        "CThread::Join() -- called for detached thread");
  456.         xncbi_Validate(!m_IsJoined,
  457.                        "CThread::Join() -- called for already joined thread");
  458.         m_IsJoined = true;
  459.     }}
  460.     // Join (wait for) and destroy
  461. #if defined(NCBI_WIN32_THREADS)
  462.     xncbi_Validate(WaitForSingleObject(m_Handle, INFINITE) == WAIT_OBJECT_0,
  463.                    "CThread::Join() -- can not join thread");
  464.     DWORD status;
  465.     xncbi_Validate(GetExitCodeThread(m_Handle, &status) &&
  466.                    status != DWORD(STILL_ACTIVE),
  467.                    "CThread::Join() -- thread is still running after join");
  468.     xncbi_Validate(CloseHandle(m_Handle),
  469.                    "CThread::Join() -- can not close thread handle");
  470.     m_Handle = NULL;
  471. #elif defined(NCBI_POSIX_THREADS)
  472.     xncbi_Validate(pthread_join(m_Handle, 0) == 0,
  473.                    "CThread::Join() -- can not join thread");
  474. #endif
  475.     // Set exit_data value
  476.     if ( exit_data ) {
  477.         *exit_data = m_ExitData;
  478.     }
  479.     // Schedule the thread object for destruction
  480.     {{
  481.         CFastMutexGuard state_guard(s_ThreadMutex);
  482.         m_SelfRef.Reset();
  483.     }}
  484. }
  485. void CThread::Exit(void* exit_data)
  486. {
  487.     // Don't exit from the main thread
  488.     CThread* x_this = GetThreadsTls().GetValue();
  489.     xncbi_Validate(x_this != 0,
  490.                    "CThread::Exit() -- attempt to call for the main thread");
  491.     {{
  492.         CFastMutexGuard state_guard(s_ThreadMutex);
  493.         x_this->m_ExitData = exit_data;
  494.     }}
  495.     // Throw the exception to be caught by Wrapper()
  496.     throw CExitThreadException();
  497. }
  498. bool CThread::Discard(void)
  499. {
  500.     CFastMutexGuard state_guard(s_ThreadMutex);
  501.     // Do not discard after Run()
  502.     if ( m_IsRun ) {
  503.         return false;
  504.     }
  505.     // Schedule for destruction (or, destroy it right now if there is no
  506.     // other CRef<>-based references to this object left).
  507.     m_SelfRef.Reset(this);
  508.     m_SelfRef.Reset();
  509.     return true;
  510. }
  511. void CThread::OnExit(void)
  512. {
  513.     return;
  514. }
  515. void CThread::AddUsedTls(CTlsBase* tls)
  516. {
  517.     // Can not use s_ThreadMutex in POSIX since it may be already locked
  518.     CFastMutexGuard tls_cleanup_guard(s_TlsCleanupMutex);
  519.     // Get current thread object
  520.     CThread* x_this = GetThreadsTls().GetValue();
  521.     if ( x_this ) {
  522.         x_this->m_UsedTls.insert(CRef<CTlsBase>(tls));
  523.     }
  524. }
  525. void CThread::GetSystemID(TThreadSystemID* id)
  526. {
  527. #if defined(NCBI_WIN32_THREADS)
  528.     // Can not use GetCurrentThread() since it also requires
  529.     // DuplicateHandle() and CloseHandle() to be called for the result.
  530.     *id = GetCurrentThreadId();
  531. #elif defined(NCBI_POSIX_THREADS)
  532.     *id = pthread_self();
  533. #else
  534.     *id = 0;
  535. #endif
  536.     return;
  537. }
  538. END_NCBI_SCOPE
  539. /*
  540.  * ===========================================================================
  541.  * $Log: ncbithr.cpp,v $
  542.  * Revision 1000.1  2004/06/01 19:09:26  gouriano
  543.  * PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.30
  544.  *
  545.  * Revision 1.30  2004/05/14 13:59:27  gorelenk
  546.  * Added include of ncbi_pch.hpp
  547.  *
  548.  * Revision 1.29  2003/09/17 15:20:46  vasilche
  549.  * Moved atomic counter swap functions to separate file.
  550.  * Added CRef<>::AtomicResetFrom(), CRef<>::AtomicReleaseTo() methods.
  551.  *
  552.  * Revision 1.28  2003/06/27 17:28:08  ucko
  553.  * +SwapPointers
  554.  *
  555.  * Revision 1.27  2003/05/20 14:23:49  vasilche
  556.  * Added call to pthread_attr_destroy as memory leak was detected.
  557.  *
  558.  * Revision 1.26  2003/05/08 20:50:10  grichenk
  559.  * Allow MT tests to run in ST mode using CThread::fRunAllowST flag.
  560.  *
  561.  * Revision 1.25  2003/04/08 18:41:08  shomrat
  562.  * Setting the handle to NULL after closing it
  563.  *
  564.  * Revision 1.24  2003/03/10 18:57:08  kuznets
  565.  * iterate->ITERATE
  566.  *
  567.  * Revision 1.23  2002/11/04 21:29:04  grichenk
  568.  * Fixed usage of const CRef<> and CRef<> constructor
  569.  *
  570.  * Revision 1.22  2002/09/30 16:53:28  vasilche
  571.  * Fix typedef on Windows.
  572.  *
  573.  * Revision 1.21  2002/09/30 16:32:29  vasilche
  574.  * Fixed bug with self referenced CThread.
  575.  * Added bound running flag to CThread.
  576.  * Fixed concurrency level on POSIX threads.
  577.  *
  578.  * Revision 1.20  2002/09/19 20:05:43  vasilche
  579.  * Safe initialization of static mutexes
  580.  *
  581.  * Revision 1.19  2002/09/13 17:00:11  ucko
  582.  * When using POSIX threads, #include <sys/time.h> for gettimeofday().
  583.  *
  584.  * Revision 1.18  2002/09/13 15:14:49  ucko
  585.  * Give CSemaphore::TryWait an optional timeout (defaulting to 0)
  586.  *
  587.  * Revision 1.17  2002/04/11 21:08:03  ivanov
  588.  * CVS log moved to end of the file
  589.  *
  590.  * Revision 1.16  2002/04/11 20:00:45  ivanov
  591.  * Returned standard assert() vice CORE_ASSERT()
  592.  *
  593.  * Revision 1.15  2002/04/10 18:39:10  ivanov
  594.  * Changed assert() to CORE_ASSERT()
  595.  *
  596.  * Revision 1.14  2001/12/13 19:45:37  gouriano
  597.  * added xxValidateAction functions
  598.  *
  599.  * Revision 1.13  2001/12/12 17:11:23  vakatov
  600.  * [NCBI_POSIX_THREADS] CSemaphore::Post() -- assert(0) just to make sure
  601.  *
  602.  * Revision 1.12  2001/12/11 22:58:16  vakatov
  603.  * [NCBI_POSIX_THREADS] CSemaphore::Post() -- avoid throwing exception
  604.  * without unlocking the embracing mutex first
  605.  *
  606.  * Revision 1.11  2001/12/10 18:07:55  vakatov
  607.  * Added class "CSemaphore" -- application-wide semaphore
  608.  *
  609.  * Revision 1.10  2001/05/17 15:05:00  lavr
  610.  * Typos corrected
  611.  *
  612.  * Revision 1.9  2001/04/03 18:20:45  grichenk
  613.  * CThread::Exit() and CThread::Wrapper() redesigned to use
  614.  * CExitThreadException instead of system functions
  615.  *
  616.  * Revision 1.8  2001/03/30 22:57:34  grichenk
  617.  * + CThread::GetSystemID()
  618.  *
  619.  * Revision 1.7  2001/03/27 18:12:35  grichenk
  620.  * CRWLock destructor releases system resources
  621.  *
  622.  * Revision 1.5  2001/03/26 21:45:29  vakatov
  623.  * Workaround static initialization/destruction traps:  provide better
  624.  * timing control, and allow safe use of the objects which are
  625.  * either not yet initialized or already destructed. (with A.Grichenko)
  626.  *
  627.  * Revision 1.4  2001/03/13 22:43:20  vakatov
  628.  * Full redesign.
  629.  * Implemented all core functionality.
  630.  * Thoroughly tested on different platforms.
  631.  *
  632.  * Revision 1.3  2000/12/11 06:48:49  vakatov
  633.  * Revamped Mutex and RW-lock APIs
  634.  *
  635.  * Revision 1.2  2000/12/09 18:41:59  vakatov
  636.  * Fixed for the extremely smart IRIX MIPSpro73 compiler
  637.  *
  638.  * Revision 1.1  2000/12/09 00:04:21  vakatov
  639.  * First draft:  Fake implementation of Mutex and RW-lock API
  640.  *
  641.  * ===========================================================================
  642.  */