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

📄 ncbicntr.hpp

📁 ncbi源码
💻 HPP
字号:
/* * =========================================================================== * PRODUCTION $Log: ncbicntr.hpp,v $ * PRODUCTION Revision 1000.4  2004/06/01 19:07:55  gouriano * PRODUCTION PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.24 * PRODUCTION * =========================================================================== */#ifndef NCBICNTR__HPP#define NCBICNTR__HPP/*  $Id: ncbicntr.hpp,v 1000.4 2004/06/01 19:07:55 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:  Aaron Ucko***//// @file ncbictr.hpp/// Efficient atomic counters (for CObject reference counts)/// Note that the special value 0x3FFFFFFF is used to indicate/// locked counters on some platforms.#include <corelib/ncbistd.hpp>#if defined(HAVE_SCHED_YIELD) && !defined(NCBI_NO_THREADS)extern "C" {#  include <sched.h>}#  define NCBI_SCHED_INIT() int spin_counter = 0#  define NCBI_SCHED_YIELD() if ( !(++spin_counter & 3) ) sched_yield()#else#  define NCBI_SCHED_INIT()#  define NCBI_SCHED_YIELD()#endif#ifdef NCBI_COMPILER_GCC#  if NCBI_COMPILER_VERSION >= 300#    define NCBI_COMPILER_GCC3 1#  endif#elif defined(NCBI_COMPILER_ICC)#  if NCBI_COMPILER_VERSION >= 600#    define NCBI_COMPILER_ICC6#  endif#endif#undef NCBI_COUNTER_UNSIGNED#undef NCBI_COUNTER_RESERVED_VALUE#undef NCBI_COUNTER_ASM_OK#undef NCBI_COUNTER_USE_ASM#undef NCBI_COUNTER_ADD#undef NCBI_COUNTER_NEED_MUTEX// Messy system-specific details; they're mostly grouped together here// to ensure consistency.#if defined(NCBI_COMPILER_GCC) || defined(NCBI_COMPILER_WORKSHOP) || (defined(NCBI_COMPILER_KCC) && defined(NCBI_OS_LINUX)) || defined(NCBI_COMPILER_ICC6)#  define NCBI_COUNTER_ASM_OK#endif/// Define platform specific counter-related macros/values.////// TNCBIAtomicValue "type" is defined based on facilities available for a/// compiler/platform. TNCBIAtomicValue is used in the CAtomicCounter class/// for defining the internal represntation of the counter.////// Where possible NCBI_COUNTER_ADD is defined in terms of compiler/platform/// specific features.#ifdef NCBI_NO_THREADS   typedef unsigned int TNCBIAtomicValue;#  define NCBI_COUNTER_UNSIGNED 1#  define NCBI_COUNTER_ADD(p, d) ((*p) += d)#elif defined(NCBI_COUNTER_ASM_OK) && defined(__sparc) && !defined(__sparcv9)// Always use our own code on pre-V9 SPARC; GCC 3's implementation// uses a global lock.   typedef unsigned int TNCBIAtomicValue;#  define NCBI_COUNTER_UNSIGNED 1#  define NCBI_COUNTER_RESERVED_VALUE 0x3FFFFFFF#  define NCBI_COUNTER_USE_ASM 1#elif defined(NCBI_COMPILER_GCC3)#  include <bits/atomicity.h>   typedef _Atomic_word TNCBIAtomicValue;#  if NCBI_COMPILER_VERSION >= 340#    define NCBI_COUNTER_ADD(p, d) (__gnu_cxx::__exchange_and_add(p, d) + d)#  else#    define NCBI_COUNTER_ADD(p, d) (__exchange_and_add(p, d) + d)#  endif#elif defined(NCBI_COMPILER_COMPAQ)#  include <machine/builtins.h>   typedef int TNCBIAtomicValue;#  define NCBI_COUNTER_ADD(p, d) (__ATOMIC_ADD_LONG(p, d) + d)#elif defined(NCBI_OS_SOLARIS) && 0 // Kernel-only. :-/#  include <sys/atomic.h>   typedef uint32_t TNCBIAtomicValue;#  define NCBI_COUNTER_UNSIGNED 1#  define NCBI_COUNTER_ADD(p, d) atomic_add_32_nv(p, d)#elif defined(NCBI_OS_IRIX)#  include <mutex.h>   typedef __uint32_t TNCBIAtomicValue;#  define NCBI_COUNTER_UNSIGNED 1#  define NCBI_COUNTER_ADD(p, d) add_then_test32(p, d)#elif defined(NCBI_OS_AIX)#  include <sys/atomic_op.h>   typedef int TNCBIAtomicValue;#  define NCBI_COUNTER_ADD(p, d) (fetch_and_add(p, d) + d)#elif defined(NCBI_OS_DARWIN)#  ifdef __MWERKS__    // necessary so Metrowerks can compile the following header properly    // unfortunately, there's no way to save the old value of the macro,    // so NCBI_verify_save must be just a flag.#    define __NOEXTENSIONS__#    ifdef verify#      define NCBI_verify_save verify#      undef verify#    endif#  endif#  include <CoreServices/CoreServices.h>// Darwin's <AssertMacros.h> defines check as a variant of assert....#  ifdef check#    undef check#  endif#  ifdef NCBI_verify_save#    undef verify#    if defined(NDEBUG) || !defined(_DEBUG)#      define verify(expr) (void) expr#    else#      define verify(expr) assert(expr)#    endif#  endif   typedef SInt32 TNCBIAtomicValue;#  define NCBI_COUNTER_ADD(p, d) (AddAtomic(d, p) + d)#elif defined(NCBI_OS_MAC)#  include <OpenTransport.h> // Is this right?   typedef SInt32 TNCBIAtomicValue;#  define NCBI_COUNTER_ADD(p, d) OTAtomicAdd32(d, p)#elif defined(NCBI_OS_MSWIN)#  include <corelib/ncbi_os_mswin.hpp>   typedef LONG TNCBIAtomicValue;#  define NCBI_COUNTER_ADD(p, d) (InterlockedExchangeAdd(p, d) + d)#else   typedef unsigned int TNCBIAtomicValue;#  define NCBI_COUNTER_UNSIGNED 1#  if defined (NCBI_COUNTER_ASM_OK) && (defined(__i386) || defined(__sparc))#    define NCBI_COUNTER_USE_ASM 1#  else#    define NCBI_COUNTER_NEED_MUTEX 1#  endif#endif/** @addtogroup Counters * * @{ */BEGIN_NCBI_SCOPE/////////////////////////////////////////////////////////////////////////////////// CAtomicCounter --////// Define a basic atomic counter.////// Provide basic counter operations for an atomic counter represented/// internally by TNCBIAtomicValue. class CAtomicCounter{public:    typedef TNCBIAtomicValue TValue;  ///< Alias TValue for TNCBIAtomicValue    /// Get atomic counter value.    TValue Get(void) const THROWS_NONE;    /// Set atomic counter value.    void   Set(TValue new_value) THROWS_NONE;    /// Atomically add value (=delta), and return new counter value.    TValue Add(int delta) THROWS_NONE;        /// Define NCBI_COUNTER_ADD if one has not been defined.#if defined(NCBI_COUNTER_USE_ASM)    static TValue x_Add(volatile TValue* value, int delta) THROWS_NONE;#  if !defined(NCBI_COUNTER_ADD)#     define NCBI_COUNTER_ADD(value, delta) NCBI_NS_NCBI::CAtomicCounter::x_Add((value), (delta))#  endif#endifprivate:    volatile TValue m_Value;  ///< Internal counter value    // CObject's constructor needs to read m_Value directly when checking    // for the magic number left by operator new.    friend class CObject;};/////////////////////////////////////////////////////////////////////////////////// CMutableAtomicCounter --////// Define a mutable atomic counter.////// Provide mutable counter operations for an atomic counter represented/// internally by CAtomicCounter. class NCBI_XNCBI_EXPORT CMutableAtomicCounter{public:    typedef CAtomicCounter::TValue TValue; ///< Alias TValue simplifies syntax    /// Get atomic counter value.    TValue Get(void) const THROWS_NONE        { return m_Counter.Get(); }    /// Set atomic counter value.    void   Set(TValue new_value) const THROWS_NONE        { m_Counter.Set(new_value); }    /// Atomically add value (=delta), and return new counter value.    TValue Add(int delta) const THROWS_NONE        { return m_Counter.Add(delta); }private:    mutable CAtomicCounter m_Counter;      ///< Mutable atomic counter value};/* @} *///////////////////////////////////////////////////////////////////////// // Inline methodsinlineCAtomicCounter::TValue CAtomicCounter::Get(void) const THROWS_NONE{#ifdef NCBI_COUNTER_RESERVED_VALUE    TValue value = m_Value;    NCBI_SCHED_INIT();    while (value == NCBI_COUNTER_RESERVED_VALUE) {        NCBI_SCHED_YIELD();        value = m_Value;    }    return value;#else    return m_Value;#endif}inlinevoid CAtomicCounter::Set(CAtomicCounter::TValue new_value) THROWS_NONE{    m_Value = new_value;}// With WorkShop, sanely inlining assembly requires the use of ".il" files.// In order to keep the toolkit's external interface sane, we therefore// force this method out-of-line and into ncbicntr_workshop.o.#if defined(NCBI_COUNTER_USE_ASM) && (!defined(NCBI_COMPILER_WORKSHOP) || defined(NCBI_COUNTER_IMPLEMENTATION))#  ifdef NCBI_COMPILER_WORKSHOP#    ifdef __sparcv9extern "C"CAtomicCounter::TValue NCBICORE_asm_cas(CAtomicCounter::TValue new_value,                                        CAtomicCounter::TValue* address,                                        CAtomicCounter::TValue old_value);#    elif defined(__sparc)extern "C"CAtomicCounter::TValue NCBICORE_asm_swap(CAtomicCounter::TValue new_value,                                         CAtomicCounter::TValue* address);#    elif defined(__i386)extern "C"CAtomicCounter::TValue NCBICORE_asm_lock_xaddl(CAtomicCounter::TValue* address,                                               int delta);#    endif#  elseinline#  endifCAtomicCounter::TValueCAtomicCounter::x_Add(volatile CAtomicCounter::TValue* value_p, int delta)THROWS_NONE{    TValue result;    TValue* nv_value_p = const_cast<TValue*>(value_p);#  ifdef __sparcv9    NCBI_SCHED_INIT();    for (;;) {        TValue old_value = *value_p;        result = old_value + delta;        // Atomic compare-and-swap: if *value_p == old_value, swap it        // with result; otherwise, just put the current value in result.#    ifdef NCBI_COMPILER_WORKSHOP        result = NCBICORE_asm_cas(result, nv_value_p, old_value);#    else        asm volatile("cas [%3], %2, %1" : "=m" (*nv_value_p), "+r" (result)                     : "r" (old_value), "r" (nv_value_p), "m" (*nv_value_p));#    endif        if (result == old_value) { // We win            break;        }        NCBI_SCHED_YIELD();    }    result += delta;#  elif defined(__sparc)    result = NCBI_COUNTER_RESERVED_VALUE;    NCBI_SCHED_INIT();    for (;;) {#    ifdef NCBI_COMPILER_WORKSHOP        result = NCBICORE_asm_swap(result, nv_value_p);#    else        asm volatile("swap [%2], %1" : "=m" (*nv_value_p), "+r" (result)                     : "r" (nv_value_p), "m" (*nv_value_p));#    endif        if (result != NCBI_COUNTER_RESERVED_VALUE) {            break;        }        NCBI_SCHED_YIELD();    }    result += delta;    *value_p = result;#  elif defined(__i386)    // Yay CISC. ;-)#    ifdef NCBI_COMPILER_WORKSHOP    result = NCBICORE_asm_lock_xaddl(nv_value_p, delta) + delta;#    else    asm volatile("lock; xaddl %1, %0" : "=m" (*nv_value_p), "=r" (result)                 : "1" (delta), "m" (*nv_value_p));    result += delta;#    endif#  else#    error "Unsupported processor type for assembly implementation!"#  endif    return result;}#endif#if !defined(NCBI_COUNTER_NEED_MUTEX)inlineCAtomicCounter::TValue CAtomicCounter::Add(int delta) THROWS_NONE{    TValue* nv_value_p = const_cast<TValue*>(&m_Value);    return NCBI_COUNTER_ADD(nv_value_p, delta);}#endifEND_NCBI_SCOPE/** ===========================================================================** $Log: ncbicntr.hpp,v $* Revision 1000.4  2004/06/01 19:07:55  gouriano* PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.24** Revision 1.24  2004/05/14 16:15:41  dicuccio* Remove unneeded export specifier for CAtomicCounter - the class is entirely* inline for MSVC** Revision 1.23  2004/04/26 14:31:46  ucko* GCC 3.4 has moved __exchange_and_add to the __gnu_cxx namespace.* Split up "+m" constraints for GCC assembly, as versions 3.4 and up* complain about them.** Revision 1.22  2004/02/19 16:46:21  vasilche* Added spin counter before calling sched_yield().* Use volatile version of pointer for assignment in x_Add().** Revision 1.21  2004/02/18 23:28:46  ucko* Clean up after previous (mislogged) commit, and honor volatility better.** Revision 1.20  2004/02/17 20:35:23  rsmith* Deal with stray definition of verify() on Mac.** Revision 1.19  2004/02/04 00:38:03  ucko* Centralize undefinition of Darwin's check macro.** Revision 1.18  2004/02/03 19:28:30  ucko* Darwin: include the master CoreServices header because* DriverSynchronization.h is officially internal.** Revision 1.17  2003/07/11 12:47:09  siyan* Documentation changes.** Revision 1.16  2003/06/03 18:24:28  rsmith* wrap includes of sched.h (explicit and implicit) in extern "c" blocks, since Apples headers do not do it themselves.** Revision 1.15  2003/06/03 15:35:07  rsmith* OS_DARWIN's AddAtomic returns the previous value, not the incremented value as we require.** Revision 1.14  2003/05/23 18:16:07  rsmith* proper definitions for NCBI_COUNTER_ADD on Mac/Darwin** Revision 1.13  2003/03/31 14:07:04  siyan* Added doxygen support** Revision 1.12  2003/03/06 19:38:48  ucko* Make CObject a friend, so that InitCounter can read m_Value directly* rather than going through Get(), which would end up spinning forever* if it came across NCBI_COUNTER_RESERVED_VALUE.** Revision 1.11  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.10  2002/10/30 17:14:33  ucko* Enable inline asm for ICC 6, which seems to be okay with our (modern) syntax.** Revision 1.9  2002/09/20 13:51:04  vasilche* Fixed volatile argument to NCBI_COUNTER_ADD** Revision 1.8  2002/09/19 20:05:41  vasilche* Safe initialization of static mutexes** Revision 1.7  2002/08/19 19:37:17  vakatov* Use <corelib/ncbi_os_mswin.hpp> in the place of <windows.h>** Revision 1.6  2002/07/11 14:17:53  gouriano* exceptions replaced by CNcbiException-type ones** Revision 1.5  2002/05/31 17:48:56  grichenk* +CMutableAtomicCounter** Revision 1.4  2002/05/24 18:43:34  ucko* Use trivial implementation for single-threaded builds.** Revision 1.3  2002/05/24 18:06:55  ucko* Inline assembly leads to ICC compiler errors in some cases, so stop* defining NCBI_COUNTER_ASM_OK for ICC.** Revision 1.2  2002/05/24 14:20:04  ucko* Fix Intel extended assembly.* Drop use of FreeBSD <machine/atomic.h>; those functions return void.* Fix name of "nv_value_p" in Add(), and declare it only when needed.** Revision 1.1  2002/05/23 22:24:21  ucko* Use low-level atomic operations for reference counts*** ===========================================================================*/#endif  /* NCBICNTR__HPP */

⌨️ 快捷键说明

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