1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 // MARKER(update_precomp.py): autogen include statement, do not remove 29 #include "precompiled_sal.hxx" 30 31 #ifdef WNT /* avoid 'std::bad_alloc' unresolved externals */ 32 #define _CRTIMP 33 #define _NTSDK 34 #endif /* WNT */ 35 36 #ifndef INCLUDED_ALGORITHM 37 #include <algorithm> 38 #define INCLUDED_ALGORITHM 39 #endif 40 41 #ifndef INCLUDED_NEW 42 #include <new> 43 #define INCLUDED_NEW 44 #endif 45 46 #ifndef INCLUDED_STRING_H 47 #include <string.h> 48 #define INCLUDED_STRING_H 49 #endif 50 #include <osl/diagnose.h> 51 #include <rtl/alloc.h> 52 53 using std::nothrow_t; 54 55 // ======================================================================= 56 // AllocatorTraits 57 // ======================================================================= 58 59 namespace 60 { 61 62 struct AllocatorTraits 63 { 64 typedef char const signature_type[8]; 65 const signature_type & m_signature; 66 67 explicit AllocatorTraits (signature_type const & s) SAL_THROW(()) 68 : m_signature (s) 69 {} 70 71 std::size_t size (std::size_t n) const SAL_THROW(()) 72 { 73 n = std::max(n, std::size_t(1)); 74 #if OSL_DEBUG_LEVEL > 0 75 n += sizeof(signature_type); 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 p = static_cast<char*>(p) + sizeof(signature_type); 85 #endif /* OSL_DEBUG_LEVEL */ 86 return p; 87 } 88 89 void* fini (void * p) const SAL_THROW(()) 90 { 91 #if OSL_DEBUG_LEVEL > 0 92 p = static_cast<char*>(p) - sizeof(signature_type); 93 if (memcmp (p, m_signature, sizeof(signature_type)) != 0) 94 { 95 OSL_ENSURE(0, "operator delete mismatch"); 96 } 97 #endif /* OSL_DEBUG_LEVEL */ 98 return p; 99 } 100 }; 101 102 // ======================================================================= 103 104 struct VectorTraits : public AllocatorTraits 105 { 106 static const signature_type g_signature; 107 108 VectorTraits() SAL_THROW(()) 109 : AllocatorTraits (g_signature) 110 {} 111 }; 112 113 struct ScalarTraits : public AllocatorTraits 114 { 115 static const signature_type g_signature; 116 117 ScalarTraits() SAL_THROW(()) 118 : AllocatorTraits (g_signature) 119 {} 120 }; 121 122 const AllocatorTraits::signature_type VectorTraits::g_signature = "new[]()"; 123 const AllocatorTraits::signature_type ScalarTraits::g_signature = "new() "; 124 125 } // anonymous namespace 126 127 // ======================================================================= 128 // Allocator 129 // ======================================================================= 130 131 static void default_handler (void) 132 { 133 // Multithreading race in 'std::set_new_handler()' call sequence below. 134 throw std::bad_alloc(); 135 } 136 137 // ======================================================================= 138 139 static void* allocate ( 140 std::size_t n, AllocatorTraits const & rTraits) 141 SAL_THROW((std::bad_alloc)) 142 { 143 n = rTraits.size (n); 144 for (;;) 145 { 146 void * p = rtl_allocateMemory (sal_Size(n)); 147 if (p != 0) 148 return rTraits.init (p); 149 150 std::new_handler d = default_handler, f = std::set_new_handler (d); 151 if (f != d) 152 std::set_new_handler (f); 153 154 if (f == 0) 155 throw std::bad_alloc(); 156 (*f)(); 157 } 158 } 159 160 // ======================================================================= 161 162 static void* allocate ( 163 std::size_t n, AllocatorTraits const & rTraits, std::nothrow_t const &) 164 SAL_THROW(()) 165 { 166 try 167 { 168 return allocate (n, rTraits); 169 } 170 catch (std::bad_alloc const &) 171 { 172 return (0); 173 } 174 } 175 176 // ======================================================================= 177 178 static void deallocate (void * p, AllocatorTraits const & rTraits) 179 SAL_THROW(()) 180 { 181 if (p) 182 { 183 rtl_freeMemory (rTraits.fini(p)); 184 } 185 } 186 187 // ======================================================================= 188 // T * p = new T; delete p; 189 // ======================================================================= 190 191 void* SAL_CALL operator new (std::size_t n) throw (std::bad_alloc) 192 { 193 return allocate (n, ScalarTraits()); 194 } 195 196 // ======================================================================= 197 198 void SAL_CALL operator delete (void * p) throw () 199 { 200 deallocate (p, ScalarTraits()); 201 } 202 203 // ======================================================================= 204 // T * p = new(nothrow) T; delete(nothrow) p; 205 // ======================================================================= 206 207 void* SAL_CALL operator new (std::size_t n, std::nothrow_t const &) throw () 208 { 209 return allocate (n, ScalarTraits(), nothrow_t()); 210 } 211 212 // ======================================================================= 213 214 void SAL_CALL operator delete (void * p, std::nothrow_t const &) throw () 215 { 216 deallocate (p, ScalarTraits()); 217 } 218 219 // ======================================================================= 220 // T * p = new T[n]; delete[] p; 221 // ======================================================================= 222 223 void* SAL_CALL operator new[] (std::size_t n) throw (std::bad_alloc) 224 { 225 return allocate (n, VectorTraits()); 226 } 227 228 // ======================================================================= 229 230 void SAL_CALL operator delete[] (void * p) throw () 231 { 232 deallocate (p, VectorTraits()); 233 } 234 235 // ======================================================================= 236 // T * p = new(nothrow) T[n]; delete(nothrow)[] p; 237 // ======================================================================= 238 239 void* SAL_CALL operator new[] (std::size_t n, std::nothrow_t const &) throw () 240 { 241 return allocate (n, VectorTraits(), nothrow_t()); 242 } 243 244 // ======================================================================= 245 246 void SAL_CALL operator delete[] (void * p, std::nothrow_t const &) throw () 247 { 248 deallocate (p, VectorTraits()); 249 } 250 251 // ======================================================================= 252