diff options
| author | Dimitry Andric <dim@FreeBSD.org> | 2016-07-23 20:47:26 +0000 | 
|---|---|---|
| committer | Dimitry Andric <dim@FreeBSD.org> | 2016-07-23 20:47:26 +0000 | 
| commit | 51072bd6bf79ef2bc6a922079bff57c31c1effbc (patch) | |
| tree | 91a2effbc9e6f80bdbbf9eb70e06c51ad0867ea0 /src/experimental/memory_resource.cpp | |
| parent | bb5e33f003797b67974a8893f7f2930fc51b8210 (diff) | |
Notes
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 0000000000000..c01eb0823baee --- /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  | 
