stl_threads.h

来自「ARM Linux Tool 各种代码包括MTD」· C头文件 代码 · 共 513 行 · 第 1/2 页

H
513
字号
    }# else    static inline unsigned long _Atomic_swap(unsigned long * __p, unsigned long __q) {        unsigned long __result = *__p;        *__p = __q;        return __result;    }# endif// GCC extension begin#endif// GCC extension end// Locking class.  Note that this class *does not have a constructor*.// It must be initialized either statically, with __STL_MUTEX_INITIALIZER,// or dynamically, by explicitly calling the _M_initialize member function.// (This is similar to the ways that a pthreads mutex can be initialized.)// There are explicit member functions for acquiring and releasing the lock.// There is no constructor because static initialization is essential for// some uses, and only a class aggregate (see section 8.5.1 of the C++// standard) can be initialized that way.  That means we must have no// constructors, no base classes, no virtual functions, and no private or// protected members.// Helper struct.  This is a workaround for various compilers that don't// handle static variables in inline functions properly.template <int __inst>struct _STL_mutex_spin {  enum { __low_max = 30, __high_max = 1000 };  // Low if we suspect uniprocessor, high for multiprocessor.  static unsigned __max;  static unsigned __last;};template <int __inst>unsigned _STL_mutex_spin<__inst>::__max = _STL_mutex_spin<__inst>::__low_max;template <int __inst>unsigned _STL_mutex_spin<__inst>::__last = 0;// GCC extension begin#if defined(__STL_GTHREADS)#if !defined(__GTHREAD_MUTEX_INIT) && defined(__GTHREAD_MUTEX_INIT_FUNCTION)extern __gthread_mutex_t _GLIBCPP_mutex;extern __gthread_mutex_t *_GLIBCPP_mutex_address;extern __gthread_once_t _GLIBCPP_once;extern void _GLIBCPP_mutex_init (void);extern void _GLIBCPP_mutex_address_init (void);#endif#endif// GCC extension endstruct _STL_mutex_lock{// GCC extension begin#if defined(__STL_GTHREADS)  // The class must be statically initialized with __STL_MUTEX_INITIALIZER.#if !defined(__GTHREAD_MUTEX_INIT) && defined(__GTHREAD_MUTEX_INIT_FUNCTION)  volatile int _M_init_flag;  __gthread_once_t _M_once;#endif  __gthread_mutex_t _M_lock;  void _M_initialize() {#ifdef __GTHREAD_MUTEX_INIT    // There should be no code in this path given the usage rules above.#elif defined(__GTHREAD_MUTEX_INIT_FUNCTION)    if (_M_init_flag) return;    if (__gthread_once (&_GLIBCPP_once, _GLIBCPP_mutex_init) != 0        && __gthread_active_p ())      abort ();    __gthread_mutex_lock (&_GLIBCPP_mutex);    if (!_M_init_flag) {	// Even though we have a global lock, we use __gthread_once to be	// absolutely certain the _M_lock mutex is only initialized once on	// multiprocessor systems.	_GLIBCPP_mutex_address = &_M_lock;	if (__gthread_once (&_M_once, _GLIBCPP_mutex_address_init) != 0	    && __gthread_active_p ())	  abort ();	_M_init_flag = 1;    }    __gthread_mutex_unlock (&_GLIBCPP_mutex);#endif  }  void _M_acquire_lock() {#if !defined(__GTHREAD_MUTEX_INIT) && defined(__GTHREAD_MUTEX_INIT_FUNCTION)    if (!_M_init_flag) _M_initialize();#endif    __gthread_mutex_lock(&_M_lock);  }  void _M_release_lock() {#if !defined(__GTHREAD_MUTEX_INIT) && defined(__GTHREAD_MUTEX_INIT_FUNCTION)    if (!_M_init_flag) _M_initialize();#endif    __gthread_mutex_unlock(&_M_lock);  }#else// GCC extension end#if defined(__STL_SGI_THREADS) || defined(__STL_WIN32THREADS)  // It should be relatively easy to get this to work on any modern Unix.  volatile unsigned long _M_lock;  void _M_initialize() { _M_lock = 0; }  static void _S_nsec_sleep(int __log_nsec) {#     ifdef __STL_SGI_THREADS          struct timespec __ts;          /* Max sleep is 2**27nsec ~ 60msec      */          __ts.tv_sec = 0;          __ts.tv_nsec = 1L << __log_nsec;          nanosleep(&__ts, 0);#     elif defined(__STL_WIN32THREADS)          if (__log_nsec <= 20) {              Sleep(0);          } else {              Sleep(1 << (__log_nsec - 20));          }#     else#       error unimplemented#     endif  }  void _M_acquire_lock() {    volatile unsigned long* __lock = &this->_M_lock;    if (!_Atomic_swap((unsigned long*)__lock, 1)) {      return;    }    unsigned __my_spin_max = _STL_mutex_spin<0>::__max;    unsigned __my_last_spins = _STL_mutex_spin<0>::__last;    volatile unsigned __junk = 17;      // Value doesn't matter.    unsigned __i;    for (__i = 0; __i < __my_spin_max; __i++) {      if (__i < __my_last_spins/2 || *__lock) {        __junk *= __junk; __junk *= __junk;        __junk *= __junk; __junk *= __junk;        continue;      }      if (!_Atomic_swap((unsigned long*)__lock, 1)) {        // got it!        // Spinning worked.  Thus we're probably not being scheduled        // against the other process with which we were contending.        // Thus it makes sense to spin longer the next time.        _STL_mutex_spin<0>::__last = __i;        _STL_mutex_spin<0>::__max = _STL_mutex_spin<0>::__high_max;        return;      }    }    // We are probably being scheduled against the other process.  Sleep.    _STL_mutex_spin<0>::__max = _STL_mutex_spin<0>::__low_max;    for (__i = 0 ;; ++__i) {      int __log_nsec = __i + 6;      if (__log_nsec > 27) __log_nsec = 27;      if (!_Atomic_swap((unsigned long *)__lock, 1)) {        return;      }      _S_nsec_sleep(__log_nsec);    }  }  void _M_release_lock() {    volatile unsigned long* __lock = &_M_lock;#   if defined(__STL_SGI_THREADS) && defined(__GNUC__) && __mips >= 3        asm("sync");        *__lock = 0;#   elif defined(__STL_SGI_THREADS) && __mips >= 3 \         && (defined (_ABIN32) || defined(_ABI64))        __lock_release(__lock);#   else         *__lock = 0;        // This is not sufficient on many multiprocessors, since        // writes to protected variables and the lock may be reordered.#   endif  }// We no longer use win32 critical sections.// They appear to be slower in the contention-free case,// and they appear difficult to initialize without introducing a race.#elif defined(__STL_PTHREADS)  pthread_mutex_t _M_lock;  void _M_initialize()   { pthread_mutex_init(&_M_lock, NULL); }  void _M_acquire_lock() { pthread_mutex_lock(&_M_lock); }  void _M_release_lock() { pthread_mutex_unlock(&_M_lock); }#elif defined(__STL_UITHREADS)  mutex_t _M_lock;  void _M_initialize()   { mutex_init(&_M_lock, USYNC_THREAD, 0); }  void _M_acquire_lock() { mutex_lock(&_M_lock); }  void _M_release_lock() { mutex_unlock(&_M_lock); }#else /* No threads */  void _M_initialize()   {}  void _M_acquire_lock() {}  void _M_release_lock() {}#endif// GCC extension begin#endif// GCC extension end};// GCC extension begin#if defined(__STL_GTHREADS)#ifdef __GTHREAD_MUTEX_INIT#define __STL_MUTEX_INITIALIZER = { __GTHREAD_MUTEX_INIT }#elif defined(__GTHREAD_MUTEX_INIT_FUNCTION)#ifdef __GTHREAD_MUTEX_INIT_DEFAULT#define __STL_MUTEX_INITIALIZER \  = { 0, __GTHREAD_ONCE_INIT, __GTHREAD_MUTEX_INIT_DEFAULT }#else#define __STL_MUTEX_INITIALIZER = { 0, __GTHREAD_ONCE_INIT }#endif#endif#else// GCC extension end#ifdef __STL_PTHREADS// Pthreads locks must be statically initialized to something other than// the default value of zero.#   define __STL_MUTEX_INITIALIZER = { PTHREAD_MUTEX_INITIALIZER }#elif defined(__STL_UITHREADS)// UIthreads locks must be statically initialized to something other than// the default value of zero.#   define __STL_MUTEX_INITIALIZER = { DEFAULTMUTEX }#elif defined(__STL_SGI_THREADS) || defined(__STL_WIN32THREADS)#   define __STL_MUTEX_INITIALIZER = { 0 }#else#   define __STL_MUTEX_INITIALIZER#endif// GCC extension begin#endif// GCC extension end// A locking class that uses _STL_mutex_lock.  The constructor takes a// reference to an _STL_mutex_lock, and acquires a lock.  The// destructor releases the lock.  It's not clear that this is exactly// the right functionality.  It will probably change in the future.struct _STL_auto_lock{  _STL_mutex_lock& _M_lock;    _STL_auto_lock(_STL_mutex_lock& __lock) : _M_lock(__lock)    { _M_lock._M_acquire_lock(); }  ~_STL_auto_lock() { _M_lock._M_release_lock(); }private:  void operator=(const _STL_auto_lock&);  _STL_auto_lock(const _STL_auto_lock&);};} // namespace std#endif /* __SGI_STL_INTERNAL_THREADS_H */// Local Variables:// mode:C++// End:

⌨️ 快捷键说明

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