diff options
Diffstat (limited to 'contrib/libc++/src/memory.cpp')
-rw-r--r-- | contrib/libc++/src/memory.cpp | 50 |
1 files changed, 50 insertions, 0 deletions
diff --git a/contrib/libc++/src/memory.cpp b/contrib/libc++/src/memory.cpp index a892e75..3884a2b 100644 --- a/contrib/libc++/src/memory.cpp +++ b/contrib/libc++/src/memory.cpp @@ -7,7 +7,10 @@ // //===----------------------------------------------------------------------===// +#define _LIBCPP_BUILDING_MEMORY #include "memory" +#include "mutex" +#include "thread" _LIBCPP_BEGIN_NAMESPACE_STD @@ -116,6 +119,53 @@ __shared_weak_count::__get_deleter(const type_info&) const _NOEXCEPT #endif // _LIBCPP_NO_RTTI +#if __has_feature(cxx_atomic) + +static const std::size_t __sp_mut_count = 16; +static mutex mut_back[__sp_mut_count]; + +_LIBCPP_CONSTEXPR __sp_mut::__sp_mut(void* p) _NOEXCEPT + : _(p) +{ +} + +void +__sp_mut::lock() _NOEXCEPT +{ + mutex& m = *static_cast<mutex*>(_); + unsigned count = 0; + while (!m.try_lock()) + { + if (++count > 16) + { + m.lock(); + break; + } + this_thread::yield(); + } +} + +void +__sp_mut::unlock() _NOEXCEPT +{ + static_cast<mutex*>(_)->unlock(); +} + +__sp_mut& +__get_sp_mut(const void* p) +{ + static __sp_mut muts[__sp_mut_count] + { + &mut_back[ 0], &mut_back[ 1], &mut_back[ 2], &mut_back[ 3], + &mut_back[ 4], &mut_back[ 5], &mut_back[ 6], &mut_back[ 7], + &mut_back[ 8], &mut_back[ 9], &mut_back[10], &mut_back[11], + &mut_back[12], &mut_back[13], &mut_back[14], &mut_back[15] + }; + return muts[hash<const void*>()(p) & (__sp_mut_count-1)]; +} + +#endif // __has_feature(cxx_atomic) + void declare_reachable(void*) { |