Created
August 6, 2022 23:21
-
-
Save AnthonyMikh/9e4c9bb99e4ef7be5fb6f02a5f9d9a01 to your computer and use it in GitHub Desktop.
Typed versions of C memory managing utilities
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <cstddef> | |
#include <cstring> | |
#include <cstdlib> | |
// #define TYPED_TIGHT_MALLOC | |
namespace typed { | |
template <typename T> | |
T* memset_n(T *dest, int ch, std::size_t count) { | |
return static_cast<T*>(std::memset(dest, ch, count * sizeof(T))); | |
} | |
template <typename T> | |
T* memset(T *dest, int ch) { | |
return memset_n(dest, ch, 1); | |
} | |
template <typename T> | |
T* memcpy_n(T* dest, const T* src, std::size_t count) { | |
return static_cast<T*>(std::memcpy(dest, src, count * sizeof(T))); | |
} | |
template <typename T> | |
T* memcpy(T* dest, const T* src) { | |
return memcpy_n(dest, src, 1); | |
} | |
template <typename T> | |
T* memmove_n(T* dest, const T* src, std::size_t count) { | |
return static_cast<T*>(std::memmove(dest, src, count * sizeof(T))); | |
} | |
// due to strict aliasing rules typed memmove makes little sense | |
// template <typename T> | |
// T* memmove(T* dest, const T* src) { | |
// return memmove_n(dest, src, 1); | |
// } | |
#ifdef TYPED_TIGHT_MALLOC | |
template<typename T> | |
T* malloc_n(std::size_t count) { | |
return static_cast<T*>(aligned_alloc(alignof(T), count * sizeof(T))); | |
} | |
#else | |
template<typename T> | |
T* malloc_n(std::size_t count) { | |
return static_cast<T*>(std::malloc(count * sizeof(T))); | |
} | |
#endif | |
template<typename T> | |
T* malloc() { | |
return malloc_n<T>(1); | |
} | |
template<typename T> | |
T* calloc_n(std::size_t count) { | |
return static_cast<T*>(std::calloc(count, sizeof(T))); | |
} | |
template<typename T> | |
T* calloc() { | |
return calloc_n<T>(1); | |
} | |
template <typename T> | |
T* realloc(T* ptr, std::size_t count) { | |
return static_cast<T*>(std::realloc(ptr, count * sizeof(T))); | |
} | |
} // namespace typed | |
// usage example | |
struct A { | |
int a; | |
int b; | |
}; | |
void zeroify(A* a) { | |
typed::memset(a, 0); | |
} | |
void zeroify_3(A* a) { | |
typed::memset_n(a, 0, 3); | |
} | |
void copy_a(A* dest, const A* src) { | |
typed::memcpy(dest, src); | |
} | |
void copy_a_3(A* dest, const A* src) { | |
typed::memcpy_n(dest, src, 3); | |
} | |
void move_a_64(A* dest, const A* src) { | |
typed::memmove_n(dest, src, 64); | |
} | |
void alloc_and_free() { | |
auto p = typed::malloc<A>(); | |
free(p); | |
auto pp = typed::malloc_n<A>(64); | |
free(pp); | |
auto pz = typed::calloc<A>(); | |
free(pz); | |
auto original = typed::calloc_n<A>(4); | |
auto resized = typed::realloc(original, 8); | |
if (resized == nullptr) { | |
free(original); | |
} else { | |
free(resized); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment