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 n += sizeof(signature_type); 72 #endif /* OSL_DEBUG_LEVEL */ 73 return n; 74 } 75 76 void* init (void * p) const SAL_THROW(()) 77 { 78 #if OSL_DEBUG_LEVEL > 0 79 memcpy (p, m_signature, sizeof(signature_type)); 80 p = static_cast<char*>(p) + sizeof(signature_type); 81 #endif /* OSL_DEBUG_LEVEL */ 82 return p; 83 } 84 85 void* fini (void * p) const SAL_THROW(()) 86 { 87 #if OSL_DEBUG_LEVEL > 0 88 p = static_cast<char*>(p) - sizeof(signature_type); 89 if (memcmp (p, m_signature, sizeof(signature_type)) != 0) 90 { 91 OSL_ENSURE(0, "operator delete mismatch"); 92 } 93 #endif /* OSL_DEBUG_LEVEL */ 94 return p; 95 } 96 }; 97 98 // ======================================================================= 99 100 struct VectorTraits : public AllocatorTraits 101 { 102 static const signature_type g_signature; 103 104 VectorTraits() SAL_THROW(()) 105 : AllocatorTraits (g_signature) 106 {} 107 }; 108 109 struct ScalarTraits : public AllocatorTraits 110 { 111 static const signature_type g_signature; 112 113 ScalarTraits() SAL_THROW(()) 114 : AllocatorTraits (g_signature) 115 {} 116 }; 117 118 const AllocatorTraits::signature_type VectorTraits::g_signature = "new[]()"; 119 const AllocatorTraits::signature_type ScalarTraits::g_signature = "new() "; 120 121 } // anonymous namespace 122 123 // ======================================================================= 124 // Allocator 125 // ======================================================================= 126 127 static void default_handler (void) 128 { 129 // Multithreading race in 'std::set_new_handler()' call sequence below. 130 throw std::bad_alloc(); 131 } 132 133 // ======================================================================= 134 135 static void* allocate ( 136 std::size_t n, AllocatorTraits const & rTraits) 137 SAL_THROW((std::bad_alloc)) 138 { 139 n = rTraits.size (n); 140 for (;;) 141 { 142 void * p = rtl_allocateMemory (sal_Size(n)); 143 if (p != 0) 144 return rTraits.init (p); 145 146 std::new_handler d = default_handler, f = std::set_new_handler (d); 147 if (f != d) 148 std::set_new_handler (f); 149 150 if (f == 0) 151 throw std::bad_alloc(); 152 (*f)(); 153 } 154 } 155 156 // ======================================================================= 157 158 static void* allocate ( 159 std::size_t n, AllocatorTraits const & rTraits, std::nothrow_t const &) 160 SAL_THROW(()) 161 { 162 try 163 { 164 return allocate (n, rTraits); 165 } 166 catch (std::bad_alloc const &) 167 { 168 return (0); 169 } 170 } 171 172 // ======================================================================= 173 174 static void deallocate (void * p, AllocatorTraits const & rTraits) 175 SAL_THROW(()) 176 { 177 if (p) 178 { 179 rtl_freeMemory (rTraits.fini(p)); 180 } 181 } 182 183 // ======================================================================= 184 // T * p = new T; delete p; 185 // ======================================================================= 186 187 void* SAL_CALL operator new (std::size_t n) throw (std::bad_alloc) 188 { 189 return allocate (n, ScalarTraits()); 190 } 191 192 // ======================================================================= 193 194 void SAL_CALL operator delete (void * p) throw () 195 { 196 deallocate (p, ScalarTraits()); 197 } 198 199 // ======================================================================= 200 // T * p = new(nothrow) T; delete(nothrow) p; 201 // ======================================================================= 202 203 void* SAL_CALL operator new (std::size_t n, std::nothrow_t const &) throw () 204 { 205 return allocate (n, ScalarTraits(), nothrow_t()); 206 } 207 208 // ======================================================================= 209 210 void SAL_CALL operator delete (void * p, std::nothrow_t const &) throw () 211 { 212 deallocate (p, ScalarTraits()); 213 } 214 215 // ======================================================================= 216 // T * p = new T[n]; delete[] p; 217 // ======================================================================= 218 219 void* SAL_CALL operator new[] (std::size_t n) throw (std::bad_alloc) 220 { 221 return allocate (n, VectorTraits()); 222 } 223 224 // ======================================================================= 225 226 void SAL_CALL operator delete[] (void * p) throw () 227 { 228 deallocate (p, VectorTraits()); 229 } 230 231 // ======================================================================= 232 // T * p = new(nothrow) T[n]; delete(nothrow)[] p; 233 // ======================================================================= 234 235 void* SAL_CALL operator new[] (std::size_t n, std::nothrow_t const &) throw () 236 { 237 return allocate (n, VectorTraits(), nothrow_t()); 238 } 239 240 // ======================================================================= 241 242 void SAL_CALL operator delete[] (void * p, std::nothrow_t const &) throw () 243 { 244 deallocate (p, VectorTraits()); 245 } 246 247 // ======================================================================= 248