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__anon185256300111::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__anon185256300111::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__anon185256300111::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 SAL_THROW((std::bad_alloc))
150 {
151 n = rTraits.size (n);
152 for (;;)
153 {
154 void * p = rtl_allocateMemory (sal_Size(n));
155 if (p != 0)
156 return rTraits.init (p);
157
158 std::new_handler d = default_handler, f = std::set_new_handler (d);
159 if (f != d)
160 std::set_new_handler (f);
161
162 if (f == 0)
163 throw std::bad_alloc();
164 (*f)();
165 }
166 }
167
168 // =======================================================================
169
allocate(std::size_t n,AllocatorTraits const & rTraits,std::nothrow_t const &)170 static void* allocate (
171 std::size_t n, AllocatorTraits const & rTraits, std::nothrow_t const &)
172 SAL_THROW(())
173 {
174 try
175 {
176 return allocate (n, rTraits);
177 }
178 catch (std::bad_alloc const &)
179 {
180 return (0);
181 }
182 }
183
184 // =======================================================================
185
deallocate(void * p,AllocatorTraits const & rTraits)186 static void deallocate (void * p, AllocatorTraits const & rTraits)
187 SAL_THROW(())
188 {
189 if (p)
190 {
191 rtl_freeMemory (rTraits.fini(p));
192 }
193 }
194
195 // =======================================================================
196 // T * p = new T; delete p;
197 // =======================================================================
198
operator new(std::size_t n)199 void* SAL_CALL operator new (std::size_t n) throw (std::bad_alloc)
200 {
201 return allocate (n, ScalarTraits());
202 }
203
204 // =======================================================================
205
operator delete(void * p)206 void SAL_CALL operator delete (void * p) throw ()
207 {
208 deallocate (p, ScalarTraits());
209 }
210
211 // =======================================================================
212 // T * p = new(nothrow) T; delete(nothrow) p;
213 // =======================================================================
214
operator new(std::size_t n,std::nothrow_t const &)215 void* SAL_CALL operator new (std::size_t n, std::nothrow_t const &) throw ()
216 {
217 return allocate (n, ScalarTraits(), nothrow_t());
218 }
219
220 // =======================================================================
221
operator delete(void * p,std::nothrow_t const &)222 void SAL_CALL operator delete (void * p, std::nothrow_t const &) throw ()
223 {
224 deallocate (p, ScalarTraits());
225 }
226
227 // =======================================================================
228 // T * p = new T[n]; delete[] p;
229 // =======================================================================
230
operator new[](std::size_t n)231 void* SAL_CALL operator new[] (std::size_t n) throw (std::bad_alloc)
232 {
233 return allocate (n, VectorTraits());
234 }
235
236 // =======================================================================
237
operator delete[](void * p)238 void SAL_CALL operator delete[] (void * p) throw ()
239 {
240 deallocate (p, VectorTraits());
241 }
242
243 // =======================================================================
244 // T * p = new(nothrow) T[n]; delete(nothrow)[] p;
245 // =======================================================================
246
operator new[](std::size_t n,std::nothrow_t const &)247 void* SAL_CALL operator new[] (std::size_t n, std::nothrow_t const &) throw ()
248 {
249 return allocate (n, VectorTraits(), nothrow_t());
250 }
251
252 // =======================================================================
253
operator delete[](void * p,std::nothrow_t const &)254 void SAL_CALL operator delete[] (void * p, std::nothrow_t const &) throw ()
255 {
256 deallocate (p, VectorTraits());
257 }
258
259 // =======================================================================
260