1*4bdff4beSrobert //===----------------------------------------------------------------------===//
246035553Spatrick //
346035553Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
446035553Spatrick // See https://llvm.org/LICENSE.txt for license information.
546035553Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
646035553Spatrick //
746035553Spatrick //===----------------------------------------------------------------------===//
846035553Spatrick
9*4bdff4beSrobert #include <__config>
10*4bdff4beSrobert #ifdef _LIBCPP_DEPRECATED_ABI_LEGACY_LIBRARY_DEFINITIONS_FOR_INLINE_FUNCTIONS
11*4bdff4beSrobert # define _LIBCPP_SHARED_PTR_DEFINE_LEGACY_INLINE_FUNCTIONS
12*4bdff4beSrobert #endif
13*4bdff4beSrobert
14*4bdff4beSrobert #include <memory>
15*4bdff4beSrobert
1646035553Spatrick #ifndef _LIBCPP_HAS_NO_THREADS
17*4bdff4beSrobert # include <mutex>
18*4bdff4beSrobert # include <thread>
1946035553Spatrick # if defined(__ELF__) && defined(_LIBCPP_LINK_PTHREAD_LIB)
2046035553Spatrick # pragma comment(lib, "pthread")
2146035553Spatrick # endif
2246035553Spatrick #endif
23*4bdff4beSrobert
2446035553Spatrick #include "include/atomic_support.h"
2546035553Spatrick
2646035553Spatrick _LIBCPP_BEGIN_NAMESPACE_STD
2746035553Spatrick
2846035553Spatrick const allocator_arg_t allocator_arg = allocator_arg_t();
2946035553Spatrick
~bad_weak_ptr()3076d0caaeSpatrick bad_weak_ptr::~bad_weak_ptr() noexcept {}
3146035553Spatrick
3246035553Spatrick const char*
what() const3376d0caaeSpatrick bad_weak_ptr::what() const noexcept
3446035553Spatrick {
3546035553Spatrick return "bad_weak_ptr";
3646035553Spatrick }
3746035553Spatrick
~__shared_count()3846035553Spatrick __shared_count::~__shared_count()
3946035553Spatrick {
4046035553Spatrick }
4146035553Spatrick
~__shared_weak_count()4246035553Spatrick __shared_weak_count::~__shared_weak_count()
4346035553Spatrick {
4446035553Spatrick }
4546035553Spatrick
46*4bdff4beSrobert #if defined(_LIBCPP_SHARED_PTR_DEFINE_LEGACY_INLINE_FUNCTIONS)
4746035553Spatrick void
__add_shared()4876d0caaeSpatrick __shared_count::__add_shared() noexcept
4946035553Spatrick {
5046035553Spatrick __libcpp_atomic_refcount_increment(__shared_owners_);
5146035553Spatrick }
5246035553Spatrick
5346035553Spatrick bool
__release_shared()5476d0caaeSpatrick __shared_count::__release_shared() noexcept
5546035553Spatrick {
5646035553Spatrick if (__libcpp_atomic_refcount_decrement(__shared_owners_) == -1)
5746035553Spatrick {
5846035553Spatrick __on_zero_shared();
5946035553Spatrick return true;
6046035553Spatrick }
6146035553Spatrick return false;
6246035553Spatrick }
6346035553Spatrick
6446035553Spatrick void
__add_shared()6576d0caaeSpatrick __shared_weak_count::__add_shared() noexcept
6646035553Spatrick {
6746035553Spatrick __shared_count::__add_shared();
6846035553Spatrick }
6946035553Spatrick
7046035553Spatrick void
__add_weak()7176d0caaeSpatrick __shared_weak_count::__add_weak() noexcept
7246035553Spatrick {
7346035553Spatrick __libcpp_atomic_refcount_increment(__shared_weak_owners_);
7446035553Spatrick }
7546035553Spatrick
7646035553Spatrick void
__release_shared()7776d0caaeSpatrick __shared_weak_count::__release_shared() noexcept
7846035553Spatrick {
7946035553Spatrick if (__shared_count::__release_shared())
8046035553Spatrick __release_weak();
8146035553Spatrick }
82*4bdff4beSrobert #endif // _LIBCPP_SHARED_PTR_DEFINE_LEGACY_INLINE_FUNCTIONS
8346035553Spatrick
8446035553Spatrick void
__release_weak()8576d0caaeSpatrick __shared_weak_count::__release_weak() noexcept
8646035553Spatrick {
8746035553Spatrick // NOTE: The acquire load here is an optimization of the very
8846035553Spatrick // common case where a shared pointer is being destructed while
8946035553Spatrick // having no other contended references.
9046035553Spatrick //
9146035553Spatrick // BENEFIT: We avoid expensive atomic stores like XADD and STREX
9246035553Spatrick // in a common case. Those instructions are slow and do nasty
9346035553Spatrick // things to caches.
9446035553Spatrick //
9546035553Spatrick // IS THIS SAFE? Yes. During weak destruction, if we see that we
9646035553Spatrick // are the last reference, we know that no-one else is accessing
9746035553Spatrick // us. If someone were accessing us, then they would be doing so
9846035553Spatrick // while the last shared / weak_ptr was being destructed, and
9946035553Spatrick // that's undefined anyway.
10046035553Spatrick //
10146035553Spatrick // If we see anything other than a 0, then we have possible
10246035553Spatrick // contention, and need to use an atomicrmw primitive.
10346035553Spatrick // The same arguments don't apply for increment, where it is legal
10446035553Spatrick // (though inadvisable) to share shared_ptr references between
10546035553Spatrick // threads, and have them all get copied at once. The argument
10646035553Spatrick // also doesn't apply for __release_shared, because an outstanding
10746035553Spatrick // weak_ptr::lock() could read / modify the shared count.
10846035553Spatrick if (__libcpp_atomic_load(&__shared_weak_owners_, _AO_Acquire) == 0)
10946035553Spatrick {
11046035553Spatrick // no need to do this store, because we are about
11146035553Spatrick // to destroy everything.
11246035553Spatrick //__libcpp_atomic_store(&__shared_weak_owners_, -1, _AO_Release);
11346035553Spatrick __on_zero_shared_weak();
11446035553Spatrick }
11546035553Spatrick else if (__libcpp_atomic_refcount_decrement(__shared_weak_owners_) == -1)
11646035553Spatrick __on_zero_shared_weak();
11746035553Spatrick }
11846035553Spatrick
11946035553Spatrick __shared_weak_count*
lock()12076d0caaeSpatrick __shared_weak_count::lock() noexcept
12146035553Spatrick {
12246035553Spatrick long object_owners = __libcpp_atomic_load(&__shared_owners_);
12346035553Spatrick while (object_owners != -1)
12446035553Spatrick {
12546035553Spatrick if (__libcpp_atomic_compare_exchange(&__shared_owners_,
12646035553Spatrick &object_owners,
12746035553Spatrick object_owners+1))
12846035553Spatrick return this;
12946035553Spatrick }
13046035553Spatrick return nullptr;
13146035553Spatrick }
13246035553Spatrick
13346035553Spatrick const void*
__get_deleter(const type_info &) const13476d0caaeSpatrick __shared_weak_count::__get_deleter(const type_info&) const noexcept
13546035553Spatrick {
13646035553Spatrick return nullptr;
13746035553Spatrick }
13846035553Spatrick
139*4bdff4beSrobert #if !defined(_LIBCPP_HAS_NO_THREADS)
14046035553Spatrick
141*4bdff4beSrobert static constexpr std::size_t __sp_mut_count = 32;
142*4bdff4beSrobert static constinit __libcpp_mutex_t mut_back[__sp_mut_count] =
14346035553Spatrick {
14446035553Spatrick _LIBCPP_MUTEX_INITIALIZER, _LIBCPP_MUTEX_INITIALIZER, _LIBCPP_MUTEX_INITIALIZER, _LIBCPP_MUTEX_INITIALIZER,
14546035553Spatrick _LIBCPP_MUTEX_INITIALIZER, _LIBCPP_MUTEX_INITIALIZER, _LIBCPP_MUTEX_INITIALIZER, _LIBCPP_MUTEX_INITIALIZER,
14646035553Spatrick _LIBCPP_MUTEX_INITIALIZER, _LIBCPP_MUTEX_INITIALIZER, _LIBCPP_MUTEX_INITIALIZER, _LIBCPP_MUTEX_INITIALIZER,
147*4bdff4beSrobert _LIBCPP_MUTEX_INITIALIZER, _LIBCPP_MUTEX_INITIALIZER, _LIBCPP_MUTEX_INITIALIZER, _LIBCPP_MUTEX_INITIALIZER,
148*4bdff4beSrobert _LIBCPP_MUTEX_INITIALIZER, _LIBCPP_MUTEX_INITIALIZER, _LIBCPP_MUTEX_INITIALIZER, _LIBCPP_MUTEX_INITIALIZER,
149*4bdff4beSrobert _LIBCPP_MUTEX_INITIALIZER, _LIBCPP_MUTEX_INITIALIZER, _LIBCPP_MUTEX_INITIALIZER, _LIBCPP_MUTEX_INITIALIZER,
150*4bdff4beSrobert _LIBCPP_MUTEX_INITIALIZER, _LIBCPP_MUTEX_INITIALIZER, _LIBCPP_MUTEX_INITIALIZER, _LIBCPP_MUTEX_INITIALIZER,
15146035553Spatrick _LIBCPP_MUTEX_INITIALIZER, _LIBCPP_MUTEX_INITIALIZER, _LIBCPP_MUTEX_INITIALIZER, _LIBCPP_MUTEX_INITIALIZER
15246035553Spatrick };
15346035553Spatrick
__sp_mut(void * p)15476d0caaeSpatrick _LIBCPP_CONSTEXPR __sp_mut::__sp_mut(void* p) noexcept
155*4bdff4beSrobert : __lx_(p)
15646035553Spatrick {
15746035553Spatrick }
15846035553Spatrick
15946035553Spatrick void
lock()16076d0caaeSpatrick __sp_mut::lock() noexcept
16146035553Spatrick {
162*4bdff4beSrobert auto m = static_cast<__libcpp_mutex_t*>(__lx_);
16346035553Spatrick __libcpp_mutex_lock(m);
16446035553Spatrick }
16546035553Spatrick
16646035553Spatrick void
unlock()16776d0caaeSpatrick __sp_mut::unlock() noexcept
16846035553Spatrick {
169*4bdff4beSrobert __libcpp_mutex_unlock(static_cast<__libcpp_mutex_t*>(__lx_));
17046035553Spatrick }
17146035553Spatrick
17246035553Spatrick __sp_mut&
__get_sp_mut(const void * p)17346035553Spatrick __get_sp_mut(const void* p)
17446035553Spatrick {
175*4bdff4beSrobert static constinit __sp_mut muts[__sp_mut_count] = {
17646035553Spatrick &mut_back[ 0], &mut_back[ 1], &mut_back[ 2], &mut_back[ 3],
17746035553Spatrick &mut_back[ 4], &mut_back[ 5], &mut_back[ 6], &mut_back[ 7],
17846035553Spatrick &mut_back[ 8], &mut_back[ 9], &mut_back[10], &mut_back[11],
179*4bdff4beSrobert &mut_back[12], &mut_back[13], &mut_back[14], &mut_back[15],
180*4bdff4beSrobert &mut_back[16], &mut_back[17], &mut_back[18], &mut_back[19],
181*4bdff4beSrobert &mut_back[20], &mut_back[21], &mut_back[22], &mut_back[23],
182*4bdff4beSrobert &mut_back[24], &mut_back[25], &mut_back[26], &mut_back[27],
183*4bdff4beSrobert &mut_back[28], &mut_back[29], &mut_back[30], &mut_back[31]
18446035553Spatrick };
18546035553Spatrick return muts[hash<const void*>()(p) & (__sp_mut_count-1)];
18646035553Spatrick }
18746035553Spatrick
188*4bdff4beSrobert #endif // !defined(_LIBCPP_HAS_NO_THREADS)
18946035553Spatrick
19046035553Spatrick void*
align(size_t alignment,size_t size,void * & ptr,size_t & space)19146035553Spatrick align(size_t alignment, size_t size, void*& ptr, size_t& space)
19246035553Spatrick {
19346035553Spatrick void* r = nullptr;
19446035553Spatrick if (size <= space)
19546035553Spatrick {
19646035553Spatrick char* p1 = static_cast<char*>(ptr);
197*4bdff4beSrobert char* p2 = reinterpret_cast<char*>(reinterpret_cast<uintptr_t>(p1 + (alignment - 1)) & -alignment);
19846035553Spatrick size_t d = static_cast<size_t>(p2 - p1);
19946035553Spatrick if (d <= space - size)
20046035553Spatrick {
20146035553Spatrick r = p2;
20246035553Spatrick ptr = r;
20346035553Spatrick space -= d;
20446035553Spatrick }
20546035553Spatrick }
20646035553Spatrick return r;
20746035553Spatrick }
20846035553Spatrick
20946035553Spatrick _LIBCPP_END_NAMESPACE_STD
210