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

生物技术

开发平台:

C/C++

  1. /*
  2.  * ===========================================================================
  3.  * PRODUCTION $Log: ncbithr.hpp,v $
  4.  * PRODUCTION Revision 1000.1  2003/11/18 15:43:14  gouriano
  5.  * PRODUCTION PRODUCTION: UPGRADED [ORIGINAL] Dev-tree R1.23
  6.  * PRODUCTION
  7.  * ===========================================================================
  8.  */
  9. #ifndef CORELIB___NCBITHR__HPP
  10. #define CORELIB___NCBITHR__HPP
  11. /*  $Id: ncbithr.hpp,v 1000.1 2003/11/18 15:43:14 gouriano Exp $
  12.  * ===========================================================================
  13.  *
  14.  *                            PUBLIC DOMAIN NOTICE
  15.  *               National Center for Biotechnology Information
  16.  *
  17.  *  This software/database is a "United States Government Work" under the
  18.  *  terms of the United States Copyright Act.  It was written as part of
  19.  *  the author's official duties as a United States Government employee and
  20.  *  thus cannot be copyrighted.  This software/database is freely available
  21.  *  to the public for use. The National Library of Medicine and the U.S.
  22.  *  Government have not placed any restriction on its use or reproduction.
  23.  *
  24.  *  Although all reasonable efforts have been taken to ensure the accuracy
  25.  *  and reliability of the software and data, the NLM and the U.S.
  26.  *  Government do not and cannot warrant the performance or results that
  27.  *  may be obtained by using this software or data. The NLM and the U.S.
  28.  *  Government disclaim all warranties, express or implied, including
  29.  *  warranties of performance, merchantability or fitness for any particular
  30.  *  purpose.
  31.  *
  32.  *  Please cite the author in any work or product based on this material.
  33.  *
  34.  * ===========================================================================
  35.  *
  36.  * Author:  Denis Vakatov, Aleksey Grichenko
  37.  *
  38.  *
  39.  */
  40. /// @file ncbithr.hpp
  41. /// Multi-threading -- classes, functions, and features.
  42. ///
  43. ///   TLS:
  44. ///   -   CTlsBase         -- TLS implementation (base class for CTls<>)
  45. ///   -   CTls<>           -- thread local storage template
  46. ///
  47. ///   THREAD:
  48. ///   -   CThread          -- thread wrapper class
  49. ///
  50. #include <corelib/ncbiobj.hpp>
  51. #include <corelib/ncbithr_conf.hpp>
  52. #include <corelib/ncbimtx.hpp>
  53. #include <memory>
  54. #include <set>
  55. #include <list>
  56. BEGIN_NCBI_SCOPE
  57. /** @addtogroup Threads
  58.  *
  59.  * @{
  60.  */
  61. /////////////////////////////////////////////////////////////////////////////
  62. ///
  63. /// CTlBase --
  64. ///
  65. /// Base class for CTls<> for storing thread-specific data.
  66. class NCBI_XNCBI_EXPORT CTlsBase : public CObject
  67. {
  68.     friend class CRef<CTlsBase>;
  69.     friend class CThread;
  70. public:
  71.     typedef void (*FCleanupBase)(void* value, void* cleanup_data);
  72. protected:
  73.     /// Constructor.
  74.     CTlsBase(void);
  75.     /// Destructor.
  76.     ///
  77.     /// Cleanup data and delete TLS key.
  78.     ~CTlsBase(void);
  79.     /// Helper method to get stored thread data. 
  80.     void* x_GetValue(void) const;
  81.     /// Helper method to set thread data. 
  82.     void x_SetValue(void* value, FCleanupBase cleanup=0, void* cleanup_data=0);
  83.     /// Helper method to reset thread data. 
  84.     void x_Reset(void);
  85.     /// Helper method to discard thread data. 
  86.     void x_Discard(void);
  87. private:
  88.     TTlsKey m_Key;              ///< 
  89.     bool    m_Initialized;      ///< Indicates if thread data initialized.
  90.     /// Internal structure to store all three pointers in the same TLS.
  91.     struct STlsData {
  92.         void*        m_Value;       
  93.         FCleanupBase m_CleanupFunc;
  94.         void*        m_CleanupData;
  95.     };
  96.     /// Helper method to get the STlsData* 
  97.     STlsData* x_GetTlsData(void) const;
  98. };
  99. /////////////////////////////////////////////////////////////////////////////
  100. ///
  101. /// CTls --
  102. ///
  103. /// Define template class for thread local storage.
  104. template <class TValue>
  105. class CTls : public CTlsBase
  106. {
  107. public:
  108.     /// Get the pointer previously stored by SetValue().
  109.     ///
  110.     /// Return 0 if no value has been stored, or if Reset() was last called.
  111.     /// @sa
  112.     ///   SetValue()
  113.     TValue* GetValue(void) const
  114.     {
  115.         return reinterpret_cast<TValue*> (x_GetValue());
  116.     }
  117.     /// Define cleanup function type, FCleanup.
  118.     typedef void (*FCleanup)(TValue* value, void* cleanup_data);
  119.     /// Set value.
  120.     ///
  121.     /// Cleanup previously stored value, and set the new value.
  122.     /// The "cleanup" function and "cleanup_data" will be used to
  123.     /// destroy the new "value" in the next call to SetValue() or Reset().
  124.     /// Do not cleanup if the new value is equal to the old one.
  125.     /// @param value
  126.     ///   New value to set.
  127.     /// @param cleanup
  128.     ///   Cleanup function.
  129.     ///   Do not cleanup if default of 0 is specified or if new value is the
  130.     ///   same as old value.
  131.     /// @param cleanup_data
  132.     ///   One of the parameters to the cleanup function.
  133.     /// @sa
  134.     ///   GetValue()
  135.     void SetValue(TValue* value, FCleanup cleanup = 0, void* cleanup_data = 0)
  136.     {
  137.         x_SetValue(value,
  138.                    reinterpret_cast<FCleanupBase> (cleanup), cleanup_data);
  139.     }
  140.     /// Reset thread local storage.
  141.     ///
  142.     /// Reset thread local storage to its initial value (as it was before the
  143.     /// first call to SetValue()). Do cleanup if the cleanup function was
  144.     /// specified in the previous call to SetValue().
  145.     ///
  146.     /// Reset() will always be called automatically on the thread termination,
  147.     /// or when the TLS is destroyed.
  148.     void Reset(void) { x_Reset(); }
  149.     /// Discard thread local storage.
  150.     ///
  151.     /// Schedule the TLS to be destroyed as soon as there are no CRef to it
  152.     /// left.
  153.     void Discard(void) { x_Discard(); }
  154. };
  155. /////////////////////////////////////////////////////////////////////////////
  156. //
  157. //  CThread::
  158. //
  159. //    Thread wrapper class
  160. //
  161. //  Base class for user-defined threads. Creates the new thread, then
  162. //  calls user-provided Main() function. The thread then can be detached
  163. //  or joined. In any case, explicit destruction of the thread is prohibited.
  164. //
  165. /////////////////////////////////////////////////////////////////////////////
  166. ///
  167. /// CThread --
  168. ///
  169. /// Thread wrapper class.
  170. ///
  171. ///  Base class for user-defined threads. Creates the new thread, then
  172. ///  calls user-provided Main() function. The thread then can be detached
  173. ///  or joined. In any case, explicit destruction of the thread is prohibited.
  174. class NCBI_XNCBI_EXPORT CThread : public CObject
  175. {
  176.     friend class CRef<CThread>;
  177.     friend class CTlsBase;
  178. public:
  179.     /// Constructor.
  180.     ///
  181.     /// Must be allocated in the heap only!.
  182.     CThread(void);
  183.     /// Which mode should the thread run in.
  184.     enum ERunMode {
  185.         fRunDefault  = 0x00,    ///< Default mode
  186.         fRunDetached = 0x01,    ///< Run the thread detached (non-joinable)
  187.         fRunBound    = 0x10,    ///< Run thread in a 1:1 thread:LPW mode
  188.                                 ///< - may not be supported and will be
  189.                                 ///< ignored on some platforms
  190.         fRunUnbound  = 0x20,    //< Run thread in a N:1 thread:LPW mode
  191.                                 ///< - may not be supported and will be
  192.                                 ///< ignored on some platforms
  193.         fRunAllowST  = 0x100    ///< Allow threads to run in single thread
  194.                                 ///< builds
  195.     };
  196.     /// Bitwise OR'd flags for thread creation passed to Run().
  197.     typedef int TRunMode;
  198.     /// Run the thread.
  199.     ///
  200.     /// Create a new thread, initialize it, and call user-provided Main()
  201.     /// method.
  202.     bool Run(TRunMode flags = fRunDefault);
  203.     // Inform the thread that user does not need to wait for its termination.
  204.     // The thread object will be destroyed by Exit().
  205.     // If the thread has already been terminated by Exit, Detach() will
  206.     // also schedule the thread object for destruction.
  207.     // NOTE:  it is no more safe to use this thread object after Detach(),
  208.     //        unless there are still CRef<> based references to it!
  209.     void Detach(void);
  210.     // Wait for the thread termination.
  211.     // The thread object will be scheduled for destruction right here,
  212.     // inside Join(). Only one call to Join() is allowed.
  213.     void Join(void** exit_data = 0);
  214.     // Cancel current thread. If the thread is detached, then schedule
  215.     // the thread object for destruction.
  216.     // Cancellation is performed by throwing an exception of type
  217.     // CExitThreadException to allow destruction of all objects in
  218.     // thread's stack, so Exit() method shell not be called from any
  219.     // destructor.
  220.     static void Exit(void* exit_data);
  221.     // If the thread has not been Run() yet, then schedule the thread object
  222.     // for destruction, and return TRUE.
  223.     // Otherwise, do nothing, and return FALSE.
  224.     bool Discard(void);
  225.     // Get ID of current thread (for main thread it is always zero).
  226.     typedef unsigned int TID;
  227.     static TID GetSelf(void);
  228.     // Get system ID of the current thread - for internal use only.
  229.     // The ID is unique only while the thread is running and may be
  230.     // re-used by another thread later.
  231.     static void GetSystemID(TThreadSystemID* id);
  232. protected:
  233.     // Derived (user-created) class must provide a real thread function.
  234.     virtual void* Main(void) = 0;
  235.     // Override this to execute finalization code.
  236.     // Unlike destructor, this code will be executed before
  237.     // thread termination and as a part of the thread.
  238.     virtual void OnExit(void);
  239.     // To be called only internally!
  240.     // NOTE:  destructor of the derived (user-provided) class should be
  241.     //        declared "protected", too!
  242.     virtual ~CThread(void);
  243. private:
  244.     TID           m_ID;            // thread ID
  245.     TThreadHandle m_Handle;        // platform-dependent thread handle
  246.     bool          m_IsRun;         // if Run() was called for the thread
  247.     bool          m_IsDetached;    // if the thread is detached
  248.     bool          m_IsJoined;      // if Join() was called for the thread
  249.     bool          m_IsTerminated;  // if Exit() was called for the thread
  250.     CRef<CThread> m_SelfRef;       // "this" -- to avoid premature destruction
  251.     void*         m_ExitData;      // as returned by Main() or passed to Exit()
  252.     // Function to use (internally) as the thread's startup function
  253.     static TWrapperRes Wrapper(TWrapperArg arg);
  254.     // To store "CThread" object related to the current (running) thread
  255.     static CTls<CThread>* sm_ThreadsTls;
  256.     // Safe access to "sm_ThreadsTls"
  257.     static CTls<CThread>& GetThreadsTls(void)
  258.     {
  259.         if ( !sm_ThreadsTls ) {
  260.             CreateThreadsTls();
  261.         }
  262.         return *sm_ThreadsTls;
  263.     }
  264.     // sm_ThreadsTls initialization and cleanup functions
  265.     static void CreateThreadsTls(void);
  266.     friend void s_CleanupThreadsTls(void* /* ptr */);
  267.     // Keep all TLS references to clean them up in Exit()
  268.     typedef set< CRef<CTlsBase> > TTlsSet;
  269.     TTlsSet m_UsedTls;
  270.     static void AddUsedTls(CTlsBase* tls);
  271. };
  272. /* @} */
  273. /////////////////////////////////////////////////////////////////////////////
  274. /////////////////////////////////////////////////////////////////////////////
  275. //  IMPLEMENTATION of INLINE functions
  276. /////////////////////////////////////////////////////////////////////////////
  277. /////////////////////////////////////////////////////////////////////////////
  278. //  CTlsBase::
  279. //
  280. inline
  281. CTlsBase::STlsData* CTlsBase::x_GetTlsData(void)
  282. const
  283. {
  284.     if ( !m_Initialized ) {
  285.         return 0;
  286.     }
  287.     void* tls_data;
  288. #if defined(NCBI_WIN32_THREADS)
  289.     tls_data = TlsGetValue(m_Key);
  290. #elif defined(NCBI_POSIX_THREADS)
  291.     tls_data = pthread_getspecific(m_Key);
  292. #else
  293.     tls_data = m_Key;
  294. #endif
  295.     return static_cast<STlsData*> (tls_data);
  296. }
  297. inline
  298. void* CTlsBase::x_GetValue(void)
  299. const
  300. {
  301.     // Get TLS-stored structure
  302.     STlsData* tls_data = x_GetTlsData();
  303.     // If assigned, extract and return user data
  304.     return tls_data ? tls_data->m_Value : 0;
  305. }
  306. /////////////////////////////////////////////////////////////////////////////
  307. //  CThread::
  308. //
  309. inline
  310. CThread::TID CThread::GetSelf(void)
  311. {
  312.     // Get pointer to the current thread object
  313.     CThread* thread_ptr = GetThreadsTls().GetValue();
  314.     // If zero, it is main thread which has no CThread object
  315.     return thread_ptr ? thread_ptr->m_ID : 0/*main thread*/;
  316. }
  317. // Special value, stands for "no thread" thread ID
  318. const CThread::TID kThreadID_None = 0xFFFFFFFF;
  319. END_NCBI_SCOPE
  320. /*
  321.  * ===========================================================================
  322.  * $Log: ncbithr.hpp,v $
  323.  * Revision 1000.1  2003/11/18 15:43:14  gouriano
  324.  * PRODUCTION: UPGRADED [ORIGINAL] Dev-tree R1.23
  325.  *
  326.  * Revision 1.23  2003/11/18 11:57:58  siyan
  327.  * Changed so @addtogroup does not cross namespace boundary
  328.  *
  329.  * Revision 1.22  2003/09/17 15:20:45  vasilche
  330.  * Moved atomic counter swap functions to separate file.
  331.  * Added CRef<>::AtomicResetFrom(), CRef<>::AtomicReleaseTo() methods.
  332.  *
  333.  * Revision 1.21  2003/09/03 14:47:09  siyan
  334.  * Added documentation.
  335.  *
  336.  * Revision 1.20  2003/07/31 19:29:03  ucko
  337.  * SwapPointers: fix for Mac OS (classic and X) and AIX.
  338.  *
  339.  * Revision 1.19  2003/06/27 17:27:44  ucko
  340.  * +SwapPointers
  341.  *
  342.  * Revision 1.18  2003/05/08 20:50:08  grichenk
  343.  * Allow MT tests to run in ST mode using CThread::fRunAllowST flag.
  344.  *
  345.  * Revision 1.17  2003/03/31 13:30:13  siyan
  346.  * Minor changes to doxygen support
  347.  *
  348.  * Revision 1.16  2003/03/31 13:02:47  siyan
  349.  * Added doxygen support
  350.  *
  351.  * Revision 1.15  2002/12/18 22:53:21  dicuccio
  352.  * Added export specifier for building DLLs in windows.  Added global list of
  353.  * all such specifiers in mswin_exports.hpp, included through ncbistl.hpp
  354.  *
  355.  * Revision 1.14  2002/09/30 16:57:34  vasilche
  356.  * Removed extra comma in enum.
  357.  *
  358.  * Revision 1.13  2002/09/30 16:32:28  vasilche
  359.  * Fixed bug with self referenced CThread.
  360.  * Added bound running flag to CThread.
  361.  * Fixed concurrency level on POSIX threads.
  362.  *
  363.  * Revision 1.12  2002/09/19 20:05:41  vasilche
  364.  * Safe initialization of static mutexes
  365.  *
  366.  * Revision 1.11  2002/09/13 15:14:43  ucko
  367.  * Give CSemaphore::TryWait an optional timeout (defaulting to 0)
  368.  *
  369.  * Revision 1.10  2002/07/15 18:17:52  gouriano
  370.  * renamed CNcbiException and its descendents
  371.  *
  372.  * Revision 1.9  2002/07/11 14:17:55  gouriano
  373.  * exceptions replaced by CNcbiException-type ones
  374.  *
  375.  * Revision 1.8  2002/04/11 20:39:19  ivanov
  376.  * CVS log moved to end of the file
  377.  *
  378.  * Revision 1.7  2001/12/10 18:07:53  vakatov
  379.  * Added class "CSemaphore" -- application-wide semaphore
  380.  *
  381.  * Revision 1.6  2001/05/17 14:54:33  lavr
  382.  * Typos corrected
  383.  *
  384.  * Revision 1.5  2001/03/30 22:57:32  grichenk
  385.  * + CThread::GetSystemID()
  386.  *
  387.  * Revision 1.4  2001/03/26 21:45:28  vakatov
  388.  * Workaround static initialization/destruction traps:  provide better
  389.  * timing control, and allow safe use of the objects which are
  390.  * either not yet initialized or already destructed. (with A.Grichenko)
  391.  *
  392.  * Revision 1.3  2001/03/13 22:43:19  vakatov
  393.  * Full redesign.
  394.  * Implemented all core functionality.
  395.  * Thoroughly tested on different platforms.
  396.  *
  397.  * Revision 1.2  2000/12/11 06:48:51  vakatov
  398.  * Revamped Mutex and RW-lock APIs
  399.  *
  400.  * Revision 1.1  2000/12/09 00:03:26  vakatov
  401.  * First draft:  Mutex and RW-lock API
  402.  *
  403.  * ===========================================================================
  404.  */
  405. #endif  /* NCBITHR__HPP */