xref: /trunk/main/sal/cpprt/operators_new_delete.cxx (revision d8dff77764cb74143fabc617dc8ee25d946bae78)
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 
67     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 
80     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 
93     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 
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 
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 
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 
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 
199 void* SAL_CALL operator new (std::size_t n) throw (std::bad_alloc)
200 {
201     return allocate (n, ScalarTraits());
202 }
203 
204 // =======================================================================
205 
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 
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 
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 
231 void* SAL_CALL operator new[] (std::size_t n) throw (std::bad_alloc)
232 {
233     return allocate (n, VectorTraits());
234 }
235 
236 // =======================================================================
237 
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 
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 
254 void SAL_CALL operator delete[] (void * p, std::nothrow_t const &) throw ()
255 {
256     deallocate (p, VectorTraits());
257 }
258 
259 // =======================================================================
260