// © 2016 and later: Unicode, Inc. and others. // License & terms of use: http://www.unicode.org/copyright.html /* ****************************************************************************** * * Copyright (C) 1997-2016, International Business Machines * Corporation and others. All Rights Reserved. * ****************************************************************************** * * File CMEMORY.H * * Contains stdlib.h/string.h memory functions * * @author Bertrand A. Damiba * * Modification History: * * Date Name Description * 6/20/98 Bertrand Created. * 05/03/99 stephen Changed from functions to macros. * ****************************************************************************** */ #ifndef CMEMORY_H #define CMEMORY_H #include "unicode/utypes.h" #include <stddef.h> #include <string.h> #include "unicode/localpointer.h" #include "uassert.h" #if U_DEBUG && defined(UPRV_MALLOC_COUNT) #include <stdio.h> #endif // uprv_memcpy and uprv_memmove #if defined(__clang__) #define uprv_memcpy(dst, src, size) … #define uprv_memmove(dst, src, size) … #elif defined(__GNUC__) #define uprv_memcpy … #define uprv_memmove … #else #define uprv_memcpy … #define uprv_memmove … #endif /** * \def UPRV_LENGTHOF * Convenience macro to determine the length of a fixed array at compile-time. * @param array A fixed length array * @return The length of the array, in elements * @internal */ #define UPRV_LENGTHOF(array) … #define uprv_memset(buffer, mark, size) … #define uprv_memcmp(buffer1, buffer2, size) … #define uprv_memchr(ptr, value, num) … U_CAPI void * U_EXPORT2 uprv_malloc(size_t s) U_MALLOC_ATTR U_ALLOC_SIZE_ATTR(1); U_CAPI void * U_EXPORT2 uprv_realloc(void *mem, size_t size) U_ALLOC_SIZE_ATTR(2); U_CAPI void U_EXPORT2 uprv_free(void *mem); U_CAPI void * U_EXPORT2 uprv_calloc(size_t num, size_t size) U_MALLOC_ATTR U_ALLOC_SIZE_ATTR2(1,2); /** * Get the least significant bits of a pointer (a memory address). * For example, with a mask of 3, the macro gets the 2 least significant bits, * which will be 0 if the pointer is 32-bit (4-byte) aligned. * * uintptr_t is the most appropriate integer type to cast to. */ #define U_POINTER_MASK_LSB(ptr, mask) … /** * Create & return an instance of "type" in statically allocated storage. * e.g. * static std::mutex *myMutex = STATIC_NEW(std::mutex); * To destroy an object created in this way, invoke the destructor explicitly, e.g. * myMutex->~mutex(); * DO NOT use delete. * DO NOT use with class UMutex, which has specific support for static instances. * * STATIC_NEW is intended for use when * - We want a static (or global) object. * - We don't want it to ever be destructed, or to explicitly control destruction, * to avoid use-after-destruction problems. * - We want to avoid an ordinary heap allocated object, * to avoid the possibility of memory allocation failures, and * to avoid memory leak reports, from valgrind, for example. * This is defined as a macro rather than a template function because each invocation * must define distinct static storage for the object being returned. */ #define STATIC_NEW(type) … /** * Heap clean up function, called from u_cleanup() * Clears any user heap functions from u_setMemoryFunctions() * Does NOT deallocate any remaining allocated memory. */ U_CFUNC UBool cmemory_cleanup(void); /** * A function called by <TT>uhash_remove</TT>, * <TT>uhash_close</TT>, or <TT>uhash_put</TT> to delete * an existing key or value. * @param obj A key or value stored in a hashtable * @see uprv_deleteUObject */ UObjectDeleter; /** * Deleter for UObject instances. * Works for all subclasses of UObject because it has a virtual destructor. */ U_CAPI void U_EXPORT2 uprv_deleteUObject(void *obj); #ifdef __cplusplus #include <utility> #include "unicode/uobject.h" U_NAMESPACE_BEGIN /** * "Smart pointer" class, deletes memory via uprv_free(). * For most methods see the LocalPointerBase base class. * Adds operator[] for array item access. * * @see LocalPointerBase */ template<typename T> class LocalMemory : public LocalPointerBase<T> { … }; template<typename T> inline T *LocalMemory<T>::allocateInsteadAndReset(int32_t newCapacity) { … } template<typename T> inline T *LocalMemory<T>::allocateInsteadAndCopy(int32_t newCapacity, int32_t length) { … } /** * Simple array/buffer management class using uprv_malloc() and uprv_free(). * Provides an internal array with fixed capacity. Can alias another array * or allocate one. * * The array address is properly aligned for type T. It might not be properly * aligned for types larger than T (or larger than the largest subtype of T). * * Unlike LocalMemory and LocalArray, this class never adopts * (takes ownership of) another array. * * WARNING: MaybeStackArray only works with primitive (plain-old data) types. * It does NOT know how to call a destructor! If you work with classes with * destructors, consider: * * - LocalArray in localpointer.h if you know the length ahead of time * - MaybeStackVector if you know the length at runtime */ template<typename T, int32_t stackCapacity> class MaybeStackArray { … }; template<typename T, int32_t stackCapacity> icu::MaybeStackArray<T, stackCapacity>::MaybeStackArray( MaybeStackArray <T, stackCapacity>&& src) noexcept : … { … } template<typename T, int32_t stackCapacity> inline MaybeStackArray <T, stackCapacity>& MaybeStackArray<T, stackCapacity>::operator=(MaybeStackArray <T, stackCapacity>&& src) noexcept { … } template<typename T, int32_t stackCapacity> inline T *MaybeStackArray<T, stackCapacity>::resize(int32_t newCapacity, int32_t length) { … } template<typename T, int32_t stackCapacity> inline T *MaybeStackArray<T, stackCapacity>::orphanOrClone(int32_t length, int32_t &resultCapacity) { … } /** * Variant of MaybeStackArray that allocates a header struct and an array * in one contiguous memory block, using uprv_malloc() and uprv_free(). * Provides internal memory with fixed array capacity. Can alias another memory * block or allocate one. * The stackCapacity is the number of T items in the internal memory, * not counting the H header. * Unlike LocalMemory and LocalArray, this class never adopts * (takes ownership of) another memory block. */ template<typename H, typename T, int32_t stackCapacity> class MaybeStackHeaderAndArray { … }; template<typename H, typename T, int32_t stackCapacity> inline H *MaybeStackHeaderAndArray<H, T, stackCapacity>::resize(int32_t newCapacity, int32_t length) { … } template<typename H, typename T, int32_t stackCapacity> inline H *MaybeStackHeaderAndArray<H, T, stackCapacity>::orphanOrClone(int32_t length, int32_t &resultCapacity) { … } /** * A simple memory management class that creates new heap allocated objects (of * any class that has a public constructor), keeps track of them and eventually * deletes them all in its own destructor. * * A typical use-case would be code like this: * * MemoryPool<MyType> pool; * * MyType* o1 = pool.create(); * if (o1 != nullptr) { * foo(o1); * } * * MyType* o2 = pool.create(1, 2, 3); * if (o2 != nullptr) { * bar(o2); * } * * // MemoryPool will take care of deleting the MyType objects. * * It doesn't do anything more than that, and is intentionally kept minimalist. */ template<typename T, int32_t stackCapacity = 8> class MemoryPool : public UMemory { … }; /** * An internal Vector-like implementation based on MemoryPool. * * Heap-allocates each element and stores pointers. * * To append an item to the vector, use emplaceBack. * * MaybeStackVector<MyType> vector; * MyType* element = vector.emplaceBack(); * if (!element) { * status = U_MEMORY_ALLOCATION_ERROR; * } * // do stuff with element * * To loop over the vector, use a for loop with indices: * * for (int32_t i = 0; i < vector.length(); i++) { * MyType* element = vector[i]; * } */ template<typename T, int32_t stackCapacity = 8> class MaybeStackVector : protected MemoryPool<T, stackCapacity> { … }; U_NAMESPACE_END #endif /* __cplusplus */ #endif /* CMEMORY_H */