1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22
23
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_sal.hxx"
26
27 #ifdef WNT /* avoid 'std::bad_alloc' unresolved externals */
28 #define _CRTIMP
29 #define _NTSDK
30 #endif /* WNT */
31
32 #ifndef INCLUDED_ALGORITHM
33 #include <algorithm>
34 #define INCLUDED_ALGORITHM
35 #endif
36
37 #ifndef INCLUDED_NEW
38 #include <new>
39 #define INCLUDED_NEW
40 #endif
41
42 #ifndef INCLUDED_STRING_H
43 #include <string.h>
44 #define INCLUDED_STRING_H
45 #endif
46 #include <osl/diagnose.h>
47 #include <rtl/alloc.h>
48
49 using std::nothrow_t;
50
51 // =======================================================================
52 // AllocatorTraits
53 // =======================================================================
54
55 namespace
56 {
57
58 struct AllocatorTraits
59 {
60 typedef char const signature_type[8];
61 const signature_type & m_signature;
62
63 explicit AllocatorTraits (signature_type const & s) SAL_THROW(())
64 : m_signature (s)
65 {}
66
size__anon7200b5f80111::AllocatorTraits67 std::size_t size (std::size_t n) const SAL_THROW(())
68 {
69 n = std::max(n, std::size_t(1));
70 #if OSL_DEBUG_LEVEL > 0
71 # ifdef NEED_ALIGN16
72 n += 2*sizeof(signature_type);
73 # else
74 n += sizeof(signature_type);
75 # endif
76 #endif /* OSL_DEBUG_LEVEL */
77 return n;
78 }
79
init__anon7200b5f80111::AllocatorTraits80 void* init (void * p) const SAL_THROW(())
81 {
82 #if OSL_DEBUG_LEVEL > 0
83 memcpy (p, m_signature, sizeof(signature_type));
84 # ifdef NEED_ALIGN16
85 p = static_cast<char*>(p) + 2*sizeof(signature_type);
86 # else
87 p = static_cast<char*>(p) + sizeof(signature_type);
88 # endif
89 #endif /* OSL_DEBUG_LEVEL */
90 return p;
91 }
92
fini__anon7200b5f80111::AllocatorTraits93 void* fini (void * p) const SAL_THROW(())
94 {
95 #if OSL_DEBUG_LEVEL > 0
96 # ifdef NEED_ALIGN16
97 p = static_cast<char*>(p) - 2*sizeof(signature_type);
98 # else
99 p = static_cast<char*>(p) - sizeof(signature_type);
100 # endif
101 if (memcmp (p, m_signature, sizeof(signature_type)) != 0)
102 {
103 OSL_ENSURE(0, "operator delete mismatch");
104 }
105 #endif /* OSL_DEBUG_LEVEL */
106 return p;
107 }
108 };
109
110 // =======================================================================
111
112 struct VectorTraits : public AllocatorTraits
113 {
114 static const signature_type g_signature;
115
116 VectorTraits() SAL_THROW(())
117 : AllocatorTraits (g_signature)
118 {}
119 };
120
121 struct ScalarTraits : public AllocatorTraits
122 {
123 static const signature_type g_signature;
124
125 ScalarTraits() SAL_THROW(())
126 : AllocatorTraits (g_signature)
127 {}
128 };
129
130 const AllocatorTraits::signature_type VectorTraits::g_signature = "new[]()";
131 const AllocatorTraits::signature_type ScalarTraits::g_signature = "new() ";
132
133 } // anonymous namespace
134
135 // =======================================================================
136 // Allocator
137 // =======================================================================
138
default_handler(void)139 static void default_handler (void)
140 {
141 // Multithreading race in 'std::set_new_handler()' call sequence below.
142 throw std::bad_alloc();
143 }
144
145 // =======================================================================
146
allocate(std::size_t n,AllocatorTraits const & rTraits)147 static void* allocate (
148 std::size_t n, AllocatorTraits const & rTraits)
149 {
150 n = rTraits.size (n);
151 for (;;)
152 {
153 void * p = rtl_allocateMemory (sal_Size(n));
154 if (p != 0)
155 return rTraits.init (p);
156
157 std::new_handler d = default_handler, f = std::set_new_handler (d);
158 if (f != d)
159 std::set_new_handler (f);
160
161 if (f == 0)
162 throw std::bad_alloc();
163 (*f)();
164 }
165 }
166
167 // =======================================================================
168
allocate(std::size_t n,AllocatorTraits const & rTraits,std::nothrow_t const &)169 static void* allocate (
170 std::size_t n, AllocatorTraits const & rTraits, std::nothrow_t const &)
171 SAL_THROW(())
172 {
173 try
174 {
175 return allocate (n, rTraits);
176 }
177 catch (std::bad_alloc const &)
178 {
179 return (0);
180 }
181 }
182
183 // =======================================================================
184
deallocate(void * p,AllocatorTraits const & rTraits)185 static void deallocate (void * p, AllocatorTraits const & rTraits)
186 SAL_THROW(())
187 {
188 if (p)
189 {
190 rtl_freeMemory (rTraits.fini(p));
191 }
192 }
193
194 // =======================================================================
195 // T * p = new T; delete p;
196 // =======================================================================
197
operator new(std::size_t n)198 void* SAL_CALL operator new (std::size_t n)
199 {
200 return allocate (n, ScalarTraits());
201 }
202
203 // =======================================================================
204
operator delete(void * p)205 void SAL_CALL operator delete (void * p) throw ()
206 {
207 deallocate (p, ScalarTraits());
208 }
209
210 // =======================================================================
211 // T * p = new(nothrow) T; delete(nothrow) p;
212 // =======================================================================
213
operator new(std::size_t n,std::nothrow_t const &)214 void* SAL_CALL operator new (std::size_t n, std::nothrow_t const &) throw ()
215 {
216 return allocate (n, ScalarTraits(), nothrow_t());
217 }
218
219 // =======================================================================
220
operator delete(void * p,std::nothrow_t const &)221 void SAL_CALL operator delete (void * p, std::nothrow_t const &) throw ()
222 {
223 deallocate (p, ScalarTraits());
224 }
225
226 // =======================================================================
227 // T * p = new T[n]; delete[] p;
228 // =======================================================================
229
operator new[](std::size_t n)230 void* SAL_CALL operator new[] (std::size_t n)
231 {
232 return allocate (n, VectorTraits());
233 }
234
235 // =======================================================================
236
operator delete[](void * p)237 void SAL_CALL operator delete[] (void * p) throw ()
238 {
239 deallocate (p, VectorTraits());
240 }
241
242 // =======================================================================
243 // T * p = new(nothrow) T[n]; delete(nothrow)[] p;
244 // =======================================================================
245
operator new[](std::size_t n,std::nothrow_t const &)246 void* SAL_CALL operator new[] (std::size_t n, std::nothrow_t const &) throw ()
247 {
248 return allocate (n, VectorTraits(), nothrow_t());
249 }
250
251 // =======================================================================
252
operator delete[](void * p,std::nothrow_t const &)253 void SAL_CALL operator delete[] (void * p, std::nothrow_t const &) throw ()
254 {
255 deallocate (p, VectorTraits());
256 }
257
258 // =======================================================================
259