diff options
Diffstat (limited to 'src/experimental/memory_resource.cpp')
-rw-r--r-- | src/experimental/memory_resource.cpp | 144 |
1 files changed, 144 insertions, 0 deletions
diff --git a/src/experimental/memory_resource.cpp b/src/experimental/memory_resource.cpp new file mode 100644 index 000000000000..c01eb0823bae --- /dev/null +++ b/src/experimental/memory_resource.cpp @@ -0,0 +1,144 @@ +//===------------------------ memory_resource.cpp -------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "experimental/memory_resource" + +#ifndef _LIBCPP_HAS_NO_ATOMIC_HEADER +#include "atomic" +#elif !defined(_LIBCPP_HAS_NO_THREADS) +#include "mutex" +#endif + +_LIBCPP_BEGIN_NAMESPACE_LFTS_PMR + +// memory_resource + +//memory_resource::~memory_resource() {} + +// new_delete_resource() + +class _LIBCPP_TYPE_VIS_ONLY __new_delete_memory_resource_imp + : public memory_resource +{ +public: + ~__new_delete_memory_resource_imp() = default; + +protected: + virtual void* do_allocate(size_t __size, size_t __align) + { return __allocate(__size); } + + virtual void do_deallocate(void * __p, size_t, size_t) + { __deallocate(__p); } + + virtual bool do_is_equal(memory_resource const & __other) const _NOEXCEPT + { return &__other == this; } +}; + +// null_memory_resource() + +class _LIBCPP_TYPE_VIS_ONLY __null_memory_resource_imp + : public memory_resource +{ +public: + ~__null_memory_resource_imp() = default; + +protected: + virtual void* do_allocate(size_t, size_t) { +#ifndef _LIBCPP_NO_EXCEPTIONS + throw std::bad_alloc(); +#else + abort(); +#endif + } + virtual void do_deallocate(void *, size_t, size_t) {} + virtual bool do_is_equal(memory_resource const & __other) const _NOEXCEPT + { return &__other == this; } +}; + +namespace { + +union ResourceInitHelper { + struct { + __new_delete_memory_resource_imp new_delete_res; + __null_memory_resource_imp null_res; + } resources; + char dummy; + _LIBCPP_CONSTEXPR_AFTER_CXX11 ResourceInitHelper() : resources() {} + ~ResourceInitHelper() {} +}; +// When compiled in C++14 this initialization should be a constant expression. +// Only in C++11 is "init_priority" needed to ensure initialization order. +ResourceInitHelper res_init __attribute__((init_priority (101))); + +} // end namespace + + +memory_resource * new_delete_resource() _NOEXCEPT { + return &res_init.resources.new_delete_res; +} + +memory_resource * null_memory_resource() _NOEXCEPT { + return &res_init.resources.null_res; +} + +// default_memory_resource() + +static memory_resource * +__default_memory_resource(bool set = false, memory_resource * new_res = nullptr) _NOEXCEPT +{ +#ifndef _LIBCPP_HAS_NO_ATOMIC_HEADER + static atomic<memory_resource*> __res = + ATOMIC_VAR_INIT(&res_init.resources.new_delete_res); + if (set) { + new_res = new_res ? new_res : new_delete_resource(); + // TODO: Can a weaker ordering be used? + return _VSTD::atomic_exchange_explicit( + &__res, new_res, memory_order::memory_order_acq_rel); + } + else { + return _VSTD::atomic_load_explicit( + &__res, memory_order::memory_order_acquire); + } +#elif !defined(_LIBCPP_HAS_NO_THREADS) + static memory_resource * res = &res_init.resources.new_delete_res; + static mutex res_lock; + if (set) { + new_res = new_res ? new_res : new_delete_resource(); + lock_guard<mutex> guard(res_lock); + memory_resource * old_res = res; + res = new_res; + return old_res; + } else { + lock_guard<mutex> guard(res_lock); + return res; + } +#else + static memory_resource* res = &res_init.resources.new_delete_res; + if (set) { + new_res = new_res ? new_res : new_delete_resource(); + memory_resource * old_res = res; + res = new_res; + return old_res; + } else { + return res; + } +#endif +} + +memory_resource * get_default_resource() _NOEXCEPT +{ + return __default_memory_resource(); +} + +memory_resource * set_default_resource(memory_resource * __new_res) _NOEXCEPT +{ + return __default_memory_resource(true, __new_res); +} + +_LIBCPP_END_NAMESPACE_LFTS_PMR
\ No newline at end of file |