📄 ncbithr.hpp
字号:
/* * =========================================================================== * PRODUCTION $Log: ncbithr.hpp,v $ * PRODUCTION Revision 1000.1 2003/11/18 15:43:14 gouriano * PRODUCTION PRODUCTION: UPGRADED [ORIGINAL] Dev-tree R1.23 * PRODUCTION * =========================================================================== */#ifndef CORELIB___NCBITHR__HPP#define CORELIB___NCBITHR__HPP/* $Id: ncbithr.hpp,v 1000.1 2003/11/18 15:43:14 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: Denis Vakatov, Aleksey Grichenko * * *//// @file ncbithr.hpp/// Multi-threading -- classes, functions, and features.////// TLS:/// - CTlsBase -- TLS implementation (base class for CTls<>)/// - CTls<> -- thread local storage template////// THREAD:/// - CThread -- thread wrapper class///#include <corelib/ncbiobj.hpp>#include <corelib/ncbithr_conf.hpp>#include <corelib/ncbimtx.hpp>#include <memory>#include <set>#include <list>BEGIN_NCBI_SCOPE/** @addtogroup Threads * * @{ *//////////////////////////////////////////////////////////////////////////////////// CTlBase --////// Base class for CTls<> for storing thread-specific data.class NCBI_XNCBI_EXPORT CTlsBase : public CObject{ friend class CRef<CTlsBase>; friend class CThread;public: typedef void (*FCleanupBase)(void* value, void* cleanup_data);protected: /// Constructor. CTlsBase(void); /// Destructor. /// /// Cleanup data and delete TLS key. ~CTlsBase(void); /// Helper method to get stored thread data. void* x_GetValue(void) const; /// Helper method to set thread data. void x_SetValue(void* value, FCleanupBase cleanup=0, void* cleanup_data=0); /// Helper method to reset thread data. void x_Reset(void); /// Helper method to discard thread data. void x_Discard(void);private: TTlsKey m_Key; ///< bool m_Initialized; ///< Indicates if thread data initialized. /// Internal structure to store all three pointers in the same TLS. struct STlsData { void* m_Value; FCleanupBase m_CleanupFunc; void* m_CleanupData; }; /// Helper method to get the STlsData* STlsData* x_GetTlsData(void) const;};/////////////////////////////////////////////////////////////////////////////////// CTls --////// Define template class for thread local storage.template <class TValue>class CTls : public CTlsBase{public: /// Get the pointer previously stored by SetValue(). /// /// Return 0 if no value has been stored, or if Reset() was last called. /// @sa /// SetValue() TValue* GetValue(void) const { return reinterpret_cast<TValue*> (x_GetValue()); } /// Define cleanup function type, FCleanup. typedef void (*FCleanup)(TValue* value, void* cleanup_data); /// Set value. /// /// Cleanup previously stored value, and set the new value. /// The "cleanup" function and "cleanup_data" will be used to /// destroy the new "value" in the next call to SetValue() or Reset(). /// Do not cleanup if the new value is equal to the old one. /// @param value /// New value to set. /// @param cleanup /// Cleanup function. /// Do not cleanup if default of 0 is specified or if new value is the /// same as old value. /// @param cleanup_data /// One of the parameters to the cleanup function. /// @sa /// GetValue() void SetValue(TValue* value, FCleanup cleanup = 0, void* cleanup_data = 0) { x_SetValue(value, reinterpret_cast<FCleanupBase> (cleanup), cleanup_data); } /// Reset thread local storage. /// /// Reset thread local storage to its initial value (as it was before the /// first call to SetValue()). Do cleanup if the cleanup function was /// specified in the previous call to SetValue(). /// /// Reset() will always be called automatically on the thread termination, /// or when the TLS is destroyed. void Reset(void) { x_Reset(); } /// Discard thread local storage. /// /// Schedule the TLS to be destroyed as soon as there are no CRef to it /// left. void Discard(void) { x_Discard(); }};///////////////////////////////////////////////////////////////////////////////// CThread:://// Thread wrapper class//// Base class for user-defined threads. Creates the new thread, then// calls user-provided Main() function. The thread then can be detached// or joined. In any case, explicit destruction of the thread is prohibited.///////////////////////////////////////////////////////////////////////////////////// CThread --////// Thread wrapper class.////// Base class for user-defined threads. Creates the new thread, then/// calls user-provided Main() function. The thread then can be detached/// or joined. In any case, explicit destruction of the thread is prohibited.class NCBI_XNCBI_EXPORT CThread : public CObject{ friend class CRef<CThread>; friend class CTlsBase;public: /// Constructor. /// /// Must be allocated in the heap only!. CThread(void); /// Which mode should the thread run in. enum ERunMode { fRunDefault = 0x00, ///< Default mode fRunDetached = 0x01, ///< Run the thread detached (non-joinable) fRunBound = 0x10, ///< Run thread in a 1:1 thread:LPW mode ///< - may not be supported and will be ///< ignored on some platforms fRunUnbound = 0x20, //< Run thread in a N:1 thread:LPW mode ///< - may not be supported and will be ///< ignored on some platforms fRunAllowST = 0x100 ///< Allow threads to run in single thread ///< builds }; /// Bitwise OR'd flags for thread creation passed to Run(). typedef int TRunMode; /// Run the thread. /// /// Create a new thread, initialize it, and call user-provided Main() /// method. bool Run(TRunMode flags = fRunDefault); // Inform the thread that user does not need to wait for its termination. // The thread object will be destroyed by Exit(). // If the thread has already been terminated by Exit, Detach() will // also schedule the thread object for destruction. // NOTE: it is no more safe to use this thread object after Detach(), // unless there are still CRef<> based references to it! void Detach(void); // Wait for the thread termination. // The thread object will be scheduled for destruction right here, // inside Join(). Only one call to Join() is allowed. void Join(void** exit_data = 0); // Cancel current thread. If the thread is detached, then schedule // the thread object for destruction. // Cancellation is performed by throwing an exception of type // CExitThreadException to allow destruction of all objects in // thread's stack, so Exit() method shell not be called from any // destructor. static void Exit(void* exit_data); // If the thread has not been Run() yet, then schedule the thread object // for destruction, and return TRUE. // Otherwise, do nothing, and return FALSE. bool Discard(void); // Get ID of current thread (for main thread it is always zero). typedef unsigned int TID; static TID GetSelf(void); // Get system ID of the current thread - for internal use only. // The ID is unique only while the thread is running and may be // re-used by another thread later. static void GetSystemID(TThreadSystemID* id);protected: // Derived (user-created) class must provide a real thread function. virtual void* Main(void) = 0; // Override this to execute finalization code. // Unlike destructor, this code will be executed before // thread termination and as a part of the thread. virtual void OnExit(void); // To be called only internally! // NOTE: destructor of the derived (user-provided) class should be // declared "protected", too! virtual ~CThread(void);private: TID m_ID; // thread ID TThreadHandle m_Handle; // platform-dependent thread handle bool m_IsRun; // if Run() was called for the thread bool m_IsDetached; // if the thread is detached bool m_IsJoined; // if Join() was called for the thread bool m_IsTerminated; // if Exit() was called for the thread CRef<CThread> m_SelfRef; // "this" -- to avoid premature destruction void* m_ExitData; // as returned by Main() or passed to Exit() // Function to use (internally) as the thread's startup function static TWrapperRes Wrapper(TWrapperArg arg); // To store "CThread" object related to the current (running) thread static CTls<CThread>* sm_ThreadsTls; // Safe access to "sm_ThreadsTls" static CTls<CThread>& GetThreadsTls(void) { if ( !sm_ThreadsTls ) { CreateThreadsTls(); } return *sm_ThreadsTls; } // sm_ThreadsTls initialization and cleanup functions static void CreateThreadsTls(void); friend void s_CleanupThreadsTls(void* /* ptr */); // Keep all TLS references to clean them up in Exit() typedef set< CRef<CTlsBase> > TTlsSet; TTlsSet m_UsedTls; static void AddUsedTls(CTlsBase* tls);};/* @} *///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// IMPLEMENTATION of INLINE functions//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// CTlsBase:://inlineCTlsBase::STlsData* CTlsBase::x_GetTlsData(void)const{ if ( !m_Initialized ) { return 0; } void* tls_data;#if defined(NCBI_WIN32_THREADS) tls_data = TlsGetValue(m_Key);#elif defined(NCBI_POSIX_THREADS) tls_data = pthread_getspecific(m_Key);#else tls_data = m_Key;#endif return static_cast<STlsData*> (tls_data);}inlinevoid* CTlsBase::x_GetValue(void)const{ // Get TLS-stored structure STlsData* tls_data = x_GetTlsData(); // If assigned, extract and return user data return tls_data ? tls_data->m_Value : 0;}/////////////////////////////////////////////////////////////////////////////// CThread:://inlineCThread::TID CThread::GetSelf(void){ // Get pointer to the current thread object CThread* thread_ptr = GetThreadsTls().GetValue(); // If zero, it is main thread which has no CThread object return thread_ptr ? thread_ptr->m_ID : 0/*main thread*/;}// Special value, stands for "no thread" thread IDconst CThread::TID kThreadID_None = 0xFFFFFFFF;END_NCBI_SCOPE/* * =========================================================================== * $Log: ncbithr.hpp,v $ * Revision 1000.1 2003/11/18 15:43:14 gouriano * PRODUCTION: UPGRADED [ORIGINAL] Dev-tree R1.23 * * Revision 1.23 2003/11/18 11:57:58 siyan * Changed so @addtogroup does not cross namespace boundary * * Revision 1.22 2003/09/17 15:20:45 vasilche * Moved atomic counter swap functions to separate file. * Added CRef<>::AtomicResetFrom(), CRef<>::AtomicReleaseTo() methods. * * Revision 1.21 2003/09/03 14:47:09 siyan * Added documentation. * * Revision 1.20 2003/07/31 19:29:03 ucko * SwapPointers: fix for Mac OS (classic and X) and AIX. * * Revision 1.19 2003/06/27 17:27:44 ucko * +SwapPointers * * Revision 1.18 2003/05/08 20:50:08 grichenk * Allow MT tests to run in ST mode using CThread::fRunAllowST flag. * * Revision 1.17 2003/03/31 13:30:13 siyan * Minor changes to doxygen support * * Revision 1.16 2003/03/31 13:02:47 siyan * Added doxygen support * * Revision 1.15 2002/12/18 22:53:21 dicuccio * Added export specifier for building DLLs in windows. Added global list of * all such specifiers in mswin_exports.hpp, included through ncbistl.hpp * * Revision 1.14 2002/09/30 16:57:34 vasilche * Removed extra comma in enum. * * Revision 1.13 2002/09/30 16:32:28 vasilche * Fixed bug with self referenced CThread. * Added bound running flag to CThread. * Fixed concurrency level on POSIX threads. * * Revision 1.12 2002/09/19 20:05:41 vasilche * Safe initialization of static mutexes * * Revision 1.11 2002/09/13 15:14:43 ucko * Give CSemaphore::TryWait an optional timeout (defaulting to 0) * * Revision 1.10 2002/07/15 18:17:52 gouriano * renamed CNcbiException and its descendents * * Revision 1.9 2002/07/11 14:17:55 gouriano * exceptions replaced by CNcbiException-type ones * * Revision 1.8 2002/04/11 20:39:19 ivanov * CVS log moved to end of the file * * Revision 1.7 2001/12/10 18:07:53 vakatov * Added class "CSemaphore" -- application-wide semaphore * * Revision 1.6 2001/05/17 14:54:33 lavr * Typos corrected * * Revision 1.5 2001/03/30 22:57:32 grichenk * + CThread::GetSystemID() * * Revision 1.4 2001/03/26 21:45:28 vakatov * Workaround static initialization/destruction traps: provide better * timing control, and allow safe use of the objects which are * either not yet initialized or already destructed. (with A.Grichenko) * * Revision 1.3 2001/03/13 22:43:19 vakatov * Full redesign. * Implemented all core functionality. * Thoroughly tested on different platforms. * * Revision 1.2 2000/12/11 06:48:51 vakatov * Revamped Mutex and RW-lock APIs * * Revision 1.1 2000/12/09 00:03:26 vakatov * First draft: Mutex and RW-lock API * * =========================================================================== */#endif /* NCBITHR__HPP */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -