GitHub Actions: Try MSVC builds with /std:c++17 and 20
[ACE_TAO.git] / ACE / ace / OS_Memory.h
blob5effb92695468114be1ba1285733a3174bdd2e3b
1 // -*- C++ -*-
3 //=============================================================================
4 /**
5 * @file OS_Memory.h
7 * @author Doug Schmidt <d.schmidt@vanderbilt.edu>
8 * @author Jesper S. M|ller<stophph@diku.dk>
9 * @author and a cast of thousands...
11 //=============================================================================
13 #ifndef ACE_OS_MEMORY_H
14 #define ACE_OS_MEMORY_H
15 #include /**/ "ace/pre.h"
17 #include /**/ "ace/ACE_export.h"
19 #if !defined (ACE_LACKS_PRAGMA_ONCE)
20 # pragma once
21 #endif /* ACE_LACKS_PRAGMA_ONCE */
23 #include "ace/OS_Errno.h"
24 #include "ace/Basic_Types.h"
25 #include "ace/os_include/os_stddef.h"
27 // Allow an installation to replace the lowest-level allocation
28 // functions without changing the source of ACE.
30 // To do this, simple #define ACE_*_FUNC macros in config.h to
31 // the names of the site-specific functions, e.g.,
33 // #define ACE_MALLOC_FUNC dlmalloc
34 // #define ACE_CALLOC_FUNC dlcalloc
35 // #define ACE_FREE_FUNC dlfree
36 // #define ACE_REALLOC_FUNC dlrealloc
38 // For completeness' sake, you should probably put
39 // #define ACE_HAS_STRDUP_EMULATION
40 // #define ACE_HAS_WCSDUP_EMULATION
41 // too, so that you guarantee that strdup() and wcsdup() call your
42 // desired mallocator and not the system mallocator.
44 #if !defined (ACE_MALLOC_FUNC)
45 # define ACE_MALLOC_FUNC ::malloc
46 #endif
47 #if !defined (ACE_CALLOC_FUNC)
48 # define ACE_CALLOC_FUNC ::calloc
49 #endif
50 #if !defined (ACE_FREE_FUNC)
51 # define ACE_FREE_FUNC ::free
52 #endif
53 #if !defined (ACE_REALLOC_FUNC)
54 # define ACE_REALLOC_FUNC ::realloc
55 #endif
57 ACE_BEGIN_VERSIONED_NAMESPACE_DECL
59 typedef void * ACE_MALLOC_T;
61 ACE_END_VERSIONED_NAMESPACE_DECL
63 // ============================================================================
64 // ACE_NEW macros
66 // A useful abstraction for expressions involving operator new since
67 // we can change memory allocation error handling policies (e.g.,
68 // depending on whether ANSI/ISO exception handling semantics are
69 // being used).
70 // ============================================================================
72 // If new(std::nothrow) is defined then, by definition, new throws exceptions.
73 #if defined (ACE_HAS_NEW_NOTHROW)
74 # if !defined (ACE_NEW_THROWS_EXCEPTIONS)
75 # define ACE_NEW_THROWS_EXCEPTIONS
76 # endif
77 #endif
79 // The Windows MFC exception mechanism requires that a caught CException
80 // (including the CMemoryException in use here) be freed using its Delete()
81 // method. Thus, when MFC is in use and we're catching exceptions as a result
82 // of new(), the exception's Delete() method has to be called. No other
83 // platform imposes this sort of restriction/requirement. The Windows
84 // config stuff (at least for MSVC/MFC) defines a ACE_del_bad_alloc macro
85 // that works with its ACE_bad_alloc macro to implement this cleanup
86 // requirement. Since no other platform requires this, define it as
87 // empty here.
88 #if !defined (ACE_del_bad_alloc)
89 # define ACE_del_bad_alloc
90 #endif
92 #if defined (ACE_NEW_THROWS_EXCEPTIONS)
94 // Since new() throws exceptions, we need a way to avoid passing
95 // exceptions past the call to new because ACE counts on having a 0
96 // return value for a failed allocation. Some compilers offer the
97 // new (nothrow) version, which does exactly what we want. Others
98 // do not. For those that do not, this sets up what exception is thrown,
99 // and then below we'll do a try/catch around the new to catch it and
100 // return a 0 pointer instead.
102 # if defined (__HP_aCC)
103 // I know this works for HP aC++... if <stdexcept> is used, it
104 // introduces other stuff that breaks things, like <memory>, which
105 // screws up auto_ptr.
106 # include /**/ <new>
107 // _HP_aCC was first defined at aC++ 03.13 on HP-UX 11. Prior to that
108 // (03.10 and before) a failed new threw bad_alloc. After that (03.13
109 // and above) the exception thrown is dependent on the below settings.
110 # if (HPUX_VERS >= 1100)
111 # if ((__HP_aCC < 32500 && !defined (RWSTD_NO_NAMESPACE)) || \
112 defined (ACE_USES_STD_NAMESPACE_FOR_STDCPP_LIB))
113 # define ACE_bad_alloc ::std::bad_alloc
114 # define ACE_nothrow ::std::nothrow
115 # define ACE_nothrow_t ::std::nothrow_t
116 # else
117 # define ACE_bad_alloc bad_alloc
118 # define ACE_nothrow nothrow
119 # define ACE_nothrow_t nothrow_t
120 # endif /* __HP_aCC */
121 # elif ((__HP_aCC < 12500 && !defined (RWSTD_NO_NAMESPACE)) || \
122 defined (ACE_USES_STD_NAMESPACE_FOR_STDCPP_LIB))
123 # define ACE_bad_alloc ::std::bad_alloc
124 # define ACE_nothrow ::std::nothrow
125 # define ACE_nothrow_t ::std::nothrow_t
126 # else
127 # define ACE_bad_alloc bad_alloc
128 # define ACE_nothrow nothrow
129 # define ACE_nothrow_t nothrow_t
130 # endif /* HPUX_VERS < 1100 */
131 # define ACE_throw_bad_alloc throw ACE_bad_alloc ()
132 # elif defined (__SUNPRO_CC)
133 # if (__SUNPRO_CC < 0x500) || (__SUNPRO_CC_COMPAT == 4)
134 # include /**/ <exception.h>
135 // Note: we catch ::xalloc rather than just xalloc because of
136 // a name clash with unsafe_ios::xalloc()
137 # define ACE_bad_alloc ::xalloc
138 # define ACE_throw_bad_alloc throw ACE_bad_alloc ("no more memory")
139 # else
140 # include /**/ <new>
141 # define ACE_bad_alloc ::std::bad_alloc
142 # if defined (ACE_HAS_NEW_NOTHROW)
143 # if defined (ACE_USES_STD_NAMESPACE_FOR_STDCPP_LIB)
144 # define ACE_nothrow ::std::nothrow
145 # define ACE_nothrow_t ::std::nothrow_t
146 # else
147 # define ACE_nothrow nothrow
148 # define ACE_nothrow_t nothrow_t
149 # endif /* ACE_USES_STD_NAMESPACE_FOR_STDCPP_LIB */
150 # endif /* ACE_HAS_NEW_NOTHROW */
151 # define ACE_throw_bad_alloc throw ACE_bad_alloc ()
152 # endif /* __SUNPRO_CC < 0x500 */
153 # elif defined (ACE_USES_STD_NAMESPACE_FOR_STDCPP_LIB)
154 # include /**/ <new>
155 # if !defined (ACE_bad_alloc)
156 # define ACE_bad_alloc ::std::bad_alloc
157 # endif
158 # define ACE_nothrow ::std::nothrow
159 # define ACE_nothrow_t ::std::nothrow_t
160 // MFC changes the behavior of operator new at all MSVC versions from 6 up.
161 # if defined (ACE_HAS_MFC) && (ACE_HAS_MFC == 1)
162 # define ACE_throw_bad_alloc AfxThrowMemoryException ()
163 # else
164 # define ACE_throw_bad_alloc throw ACE_bad_alloc ()
165 # endif
166 # else
167 # include /**/ <new>
168 # if !defined (ACE_bad_alloc)
169 # define ACE_bad_alloc bad_alloc
170 # endif
171 # define ACE_nothrow nothrow
172 # define ACE_nothrow_t nothrow_t
173 // MFC changes the behavior of operator new at all MSVC versions from 6 up.
174 # if defined (ACE_HAS_MFC) && (ACE_HAS_MFC == 1)
175 # define ACE_throw_bad_alloc AfxThrowMemoryException ()
176 # else
177 # define ACE_throw_bad_alloc throw ACE_bad_alloc ()
178 # endif
179 # endif /* __HP_aCC */
181 # if defined (ACE_HAS_NEW_NOTHROW)
182 # define ACE_NEW_RETURN(POINTER,CONSTRUCTOR,RET_VAL) \
183 do { POINTER = new (ACE_nothrow) CONSTRUCTOR; \
184 if (POINTER == 0) { errno = ENOMEM; return RET_VAL; } \
185 } while (0)
186 # define ACE_NEW(POINTER,CONSTRUCTOR) \
187 do { POINTER = new(ACE_nothrow) CONSTRUCTOR; \
188 if (POINTER == 0) { errno = ENOMEM; return; } \
189 } while (0)
190 # define ACE_NEW_NORETURN(POINTER,CONSTRUCTOR) \
191 do { POINTER = new(ACE_nothrow) CONSTRUCTOR; \
192 if (POINTER == 0) { errno = ENOMEM; } \
193 } while (0)
195 # else
197 # define ACE_NEW_RETURN(POINTER,CONSTRUCTOR,RET_VAL) \
198 do { try { POINTER = new CONSTRUCTOR; } \
199 catch (ACE_bad_alloc) { ACE_del_bad_alloc errno = ENOMEM; POINTER = 0; return RET_VAL; } \
200 } while (0)
202 # define ACE_NEW(POINTER,CONSTRUCTOR) \
203 do { try { POINTER = new CONSTRUCTOR; } \
204 catch (ACE_bad_alloc) { ACE_del_bad_alloc errno = ENOMEM; POINTER = 0; return; } \
205 } while (0)
207 # define ACE_NEW_NORETURN(POINTER,CONSTRUCTOR) \
208 do { try { POINTER = new CONSTRUCTOR; } \
209 catch (ACE_bad_alloc) { ACE_del_bad_alloc errno = ENOMEM; POINTER = 0; } \
210 } while (0)
211 # endif /* ACE_HAS_NEW_NOTHROW */
213 #else /* ACE_NEW_THROWS_EXCEPTIONS */
215 # define ACE_NEW_RETURN(POINTER,CONSTRUCTOR,RET_VAL) \
216 do { POINTER = new CONSTRUCTOR; \
217 if (POINTER == 0) { errno = ENOMEM; return RET_VAL; } \
218 } while (0)
219 # define ACE_NEW(POINTER,CONSTRUCTOR) \
220 do { POINTER = new CONSTRUCTOR; \
221 if (POINTER == 0) { errno = ENOMEM; return; } \
222 } while (0)
223 # define ACE_NEW_NORETURN(POINTER,CONSTRUCTOR) \
224 do { POINTER = new CONSTRUCTOR; \
225 if (POINTER == 0) { errno = ENOMEM; } \
226 } while (0)
228 # if !defined (ACE_bad_alloc)
229 class ACE_bad_alloc_class {};
230 # define ACE_bad_alloc ACE_bad_alloc_class
231 # endif
232 # if defined (ACE_HAS_MFC) && (ACE_HAS_MFC == 1)
233 # define ACE_throw_bad_alloc AfxThrowMemoryException ()
234 # else
235 # define ACE_throw_bad_alloc return 0
236 # endif
238 #endif /* ACE_NEW_THROWS_EXCEPTIONS */
240 ACE_BEGIN_VERSIONED_NAMESPACE_DECL
241 //@{
243 * @name Efficiently compute aligned pointers to powers of 2 boundaries.
247 * Efficiently align "value" up to "alignment", knowing that all such
248 * boundaries are binary powers and that we're using two's complement
249 * arithmetic.
251 * Since the alignment is a power of two its binary representation is:
253 * alignment = 0...010...0
255 * hence
257 * alignment - 1 = 0...001...1 = T1
259 * so the complement is:
261 * ~(alignment - 1) = 1...110...0 = T2
263 * Notice that there is a multiple of @a alignment in the range
264 * [<value>,<value> + T1], also notice that if
266 * X = ( <value> + T1 ) & T2
268 * then
270 * <value> <= X <= <value> + T1
272 * because the & operator only changes the last bits, and since X is a
273 * multiple of @a alignment (its last bits are zero) we have found the
274 * multiple we wanted.
276 /// Return the next integer aligned to a required boundary
278 * @param ptr the base pointer
279 * @param alignment the required alignment
281 #if defined (ACE_OPENVMS) && (!defined (__INITIAL_POINTER_SIZE) || (__INITIAL_POINTER_SIZE < 64))
282 inline unsigned int
283 ACE_align_binary (unsigned int ptr, unsigned int alignment)
285 unsigned int const tmp = alignment - 1;
286 return (ptr + tmp) & (~tmp);
288 #else
289 inline uintptr_t
290 ACE_align_binary (uintptr_t ptr, uintptr_t alignment)
292 uintptr_t const tmp = alignment - 1;
293 return (ptr + tmp) & (~tmp);
295 #endif
297 #if defined (ACE_OPENVMS) && (!defined (__INITIAL_POINTER_SIZE) || (__INITIAL_POINTER_SIZE < 64))
298 /// Return the next address aligned to a required boundary
299 inline char *
300 ACE_ptr_align_binary (char const * ptr, unsigned int alignment)
302 return
303 reinterpret_cast<char *> (
304 ACE_align_binary (reinterpret_cast<unsigned int> (ptr), alignment));
307 /// Return the next address aligned to a required boundary
308 inline char *
309 ACE_ptr_align_binary (unsigned char const * ptr, unsigned int alignment)
311 return
312 ACE_ptr_align_binary (reinterpret_cast<char const *> (ptr), alignment);
314 #else
315 /// Return the next address aligned to a required boundary
316 inline char *
317 ACE_ptr_align_binary (char const * ptr, uintptr_t alignment)
319 return
320 reinterpret_cast<char *> (
321 ACE_align_binary (reinterpret_cast<uintptr_t> (ptr), alignment));
324 /// Return the next address aligned to a required boundary
325 inline char *
326 ACE_ptr_align_binary (unsigned char const * ptr, uintptr_t alignment)
328 return
329 ACE_ptr_align_binary (reinterpret_cast<char const *> (ptr), alignment);
331 #endif /* ACE_OPENVMS && __INITIAL_POINTER_SIZE < 64 */
332 //@}
333 ACE_END_VERSIONED_NAMESPACE_DECL
335 #include "ace/OS_NS_stdlib.h"
337 #include /**/ "ace/post.h"
338 #endif /* ACE_OS_MEMORY_H */