1 | ////////////////////////////////////////////////////////////////////////////// |
2 | // |
3 | // (C) Copyright Ion Gaztanaga 2015-2015. Distributed under the Boost |
4 | // Software License, Version 1.0. (See accompanying file |
5 | // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) |
6 | // |
7 | // See http://www.boost.org/libs/container for documentation. |
8 | // |
9 | ////////////////////////////////////////////////////////////////////////////// |
10 | |
11 | #define BOOST_CONTAINER_SOURCE |
12 | #include <boost/container/pmr/memory_resource.hpp> |
13 | #include <boost/container/pmr/global_resource.hpp> |
14 | #include <boost/container/throw_exception.hpp> |
15 | #include <boost/container/detail/dlmalloc.hpp> //For global lock |
16 | #include <boost/container/detail/singleton.hpp> |
17 | |
18 | #include <cstddef> |
19 | #include <new> |
20 | |
21 | namespace boost { |
22 | namespace container { |
23 | namespace pmr { |
24 | |
25 | class new_delete_resource_imp |
26 | : public memory_resource |
27 | { |
28 | public: |
29 | |
30 | ~new_delete_resource_imp() BOOST_OVERRIDE |
31 | {} |
32 | |
33 | void* do_allocate(std::size_t bytes, std::size_t alignment) BOOST_OVERRIDE |
34 | { (void)bytes; (void)alignment; return new char[bytes]; } |
35 | |
36 | void do_deallocate(void* p, std::size_t bytes, std::size_t alignment) BOOST_OVERRIDE |
37 | { (void)bytes; (void)alignment; delete[]((char*)p); } |
38 | |
39 | bool do_is_equal(const memory_resource& other) const BOOST_NOEXCEPT BOOST_OVERRIDE |
40 | { return &other == this; } |
41 | }; |
42 | |
43 | struct null_memory_resource_imp |
44 | : public memory_resource |
45 | { |
46 | public: |
47 | |
48 | ~null_memory_resource_imp() BOOST_OVERRIDE |
49 | {} |
50 | |
51 | void* do_allocate(std::size_t bytes, std::size_t alignment) BOOST_OVERRIDE |
52 | { |
53 | (void)bytes; (void)alignment; |
54 | #if defined(BOOST_CONTAINER_USER_DEFINED_THROW_CALLBACKS) || defined(BOOST_NO_EXCEPTIONS) |
55 | throw_bad_alloc(); |
56 | return 0; |
57 | #else |
58 | throw std::bad_alloc(); |
59 | #endif |
60 | } |
61 | |
62 | void do_deallocate(void* p, std::size_t bytes, std::size_t alignment) BOOST_OVERRIDE |
63 | { (void)p; (void)bytes; (void)alignment; } |
64 | |
65 | bool do_is_equal(const memory_resource& other) const BOOST_NOEXCEPT BOOST_OVERRIDE |
66 | { return &other == this; } |
67 | }; |
68 | |
69 | BOOST_CONTAINER_DECL memory_resource* new_delete_resource() BOOST_NOEXCEPT |
70 | { |
71 | return &boost::container::dtl::singleton_default<new_delete_resource_imp>::instance(); |
72 | } |
73 | |
74 | BOOST_CONTAINER_DECL memory_resource* null_memory_resource() BOOST_NOEXCEPT |
75 | { |
76 | return &boost::container::dtl::singleton_default<null_memory_resource_imp>::instance(); |
77 | } |
78 | |
79 | #if defined(BOOST_NO_CXX11_HDR_ATOMIC) |
80 | |
81 | static memory_resource *default_memory_resource = |
82 | &boost::container::dtl::singleton_default<new_delete_resource_imp>::instance(); |
83 | |
84 | BOOST_CONTAINER_DECL memory_resource* set_default_resource(memory_resource* r) BOOST_NOEXCEPT |
85 | { |
86 | if(dlmalloc_global_sync_lock()){ |
87 | memory_resource *previous = default_memory_resource; |
88 | if(!previous){ |
89 | //function called before main, default_memory_resource is not initialized yet |
90 | previous = new_delete_resource(); |
91 | } |
92 | default_memory_resource = r ? r : new_delete_resource(); |
93 | dlmalloc_global_sync_unlock(); |
94 | return previous; |
95 | } |
96 | else{ |
97 | return new_delete_resource(); |
98 | } |
99 | } |
100 | |
101 | BOOST_CONTAINER_DECL memory_resource* get_default_resource() BOOST_NOEXCEPT |
102 | { |
103 | if(dlmalloc_global_sync_lock()){ |
104 | memory_resource *current = default_memory_resource; |
105 | if(!current){ |
106 | //function called before main, default_memory_resource is not initialized yet |
107 | current = new_delete_resource(); |
108 | } |
109 | dlmalloc_global_sync_unlock(); |
110 | return current; |
111 | } |
112 | else{ |
113 | return new_delete_resource(); |
114 | } |
115 | } |
116 | |
117 | #else // #if defined(BOOST_NO_CXX11_HDR_ATOMIC) |
118 | |
119 | } //namespace pmr { |
120 | } //namespace container { |
121 | } //namespace boost { |
122 | |
123 | #include <atomic> |
124 | |
125 | namespace boost { |
126 | namespace container { |
127 | namespace pmr { |
128 | |
129 | std::atomic<memory_resource*>& default_memory_resource_instance() { |
130 | static std::atomic<memory_resource*> instance(new_delete_resource()); |
131 | return instance; |
132 | } |
133 | |
134 | BOOST_CONTAINER_DECL memory_resource* set_default_resource(memory_resource* r) BOOST_NOEXCEPT |
135 | { |
136 | memory_resource *const res = r ? r : new_delete_resource(); |
137 | return default_memory_resource_instance().exchange(p: res, m: std::memory_order_acq_rel); |
138 | } |
139 | |
140 | BOOST_CONTAINER_DECL memory_resource* get_default_resource() BOOST_NOEXCEPT |
141 | { return default_memory_resource_instance().load(m: std::memory_order_acquire); } |
142 | |
143 | #endif |
144 | |
145 | } //namespace pmr { |
146 | } //namespace container { |
147 | } //namespace boost { |
148 | |