Add memory allocation interface

This commit is contained in:
KitsuneAlex
2022-01-31 19:34:42 +01:00
parent bd95b3d243
commit fffa5856de
2 changed files with 63 additions and 9 deletions

View File

@@ -106,6 +106,35 @@ static int YGDefaultLog(
#undef YG_UNUSED #undef YG_UNUSED
#endif #endif
static YGAllocatorAllocateFunc gAllocatorAllocateFunc = &malloc;
static YGAllocatorFreeFunc gAllocatorFreeFunc = &free;
YOGA_EXPORT void YGSetAllocationCallbacks(
YGAllocatorAllocateFunc allocFunc,
YGAllocatorFreeFunc freeFunc) {
gAllocatorAllocateFunc = allocFunc;
gAllocatorFreeFunc = freeFunc;
}
YOGA_EXPORT void YGGetAllocationCallbacks(
YGAllocatorAllocateFunc* allocFunc,
YGAllocatorFreeFunc* freeFunc) {
if(allocFunc != nullptr) {
*allocFunc = gAllocatorAllocateFunc;
}
if(freeFunc != nullptr) {
*freeFunc = gAllocatorFreeFunc;
}
}
YOGA_EXPORT void* YGMemoryAllocate(size_t size) {
return gAllocatorAllocateFunc(size);
}
YOGA_EXPORT void YGMemoryFree(void* memory) {
gAllocatorFreeFunc(memory);
}
static inline bool YGDoubleIsUndefined(const double value) { static inline bool YGDoubleIsUndefined(const double value) {
return facebook::yoga::isUndefined(value); return facebook::yoga::isUndefined(value);
} }
@@ -192,7 +221,7 @@ YOGA_EXPORT void YGNodeMarkDirtyAndPropogateToDescendants(
int32_t gConfigInstanceCount = 0; int32_t gConfigInstanceCount = 0;
YOGA_EXPORT WIN_EXPORT YGNodeRef YGNodeNewWithConfig(const YGConfigRef config) { YOGA_EXPORT WIN_EXPORT YGNodeRef YGNodeNewWithConfig(const YGConfigRef config) {
const YGNodeRef node = new YGNode{config}; const YGNodeRef node = YGAllocate<YGNode>(config);
YGAssertWithConfig( YGAssertWithConfig(
config, node != nullptr, "Could not allocate memory for node"); config, node != nullptr, "Could not allocate memory for node");
Event::publish<Event::NodeAllocation>(node, {config}); Event::publish<Event::NodeAllocation>(node, {config});
@@ -210,7 +239,7 @@ YOGA_EXPORT YGNodeRef YGNodeNew(void) {
} }
YOGA_EXPORT YGNodeRef YGNodeClone(YGNodeRef oldNode) { YOGA_EXPORT YGNodeRef YGNodeClone(YGNodeRef oldNode) {
YGNodeRef node = new YGNode(*oldNode); YGNodeRef node = YGAllocate<YGNode>(*oldNode);
YGAssertWithConfig( YGAssertWithConfig(
oldNode->getConfig(), oldNode->getConfig(),
node != nullptr, node != nullptr,
@@ -221,7 +250,7 @@ YOGA_EXPORT YGNodeRef YGNodeClone(YGNodeRef oldNode) {
} }
static YGConfigRef YGConfigClone(const YGConfig& oldConfig) { static YGConfigRef YGConfigClone(const YGConfig& oldConfig) {
const YGConfigRef config = new YGConfig(oldConfig); const YGConfigRef config = YGAllocate<YGConfig>(oldConfig);
YGAssert(config != nullptr, "Could not allocate memory for config"); YGAssert(config != nullptr, "Could not allocate memory for config");
gConfigInstanceCount++; gConfigInstanceCount++;
return config; return config;
@@ -229,7 +258,7 @@ static YGConfigRef YGConfigClone(const YGConfig& oldConfig) {
static YGNodeRef YGNodeDeepClone(YGNodeRef oldNode) { static YGNodeRef YGNodeDeepClone(YGNodeRef oldNode) {
auto config = YGConfigClone(*oldNode->getConfig()); auto config = YGConfigClone(*oldNode->getConfig());
auto node = new YGNode{*oldNode, config}; auto node = YGAllocate<YGNode>(*oldNode, config);
node->setOwner(nullptr); node->setOwner(nullptr);
Event::publish<Event::NodeAllocation>(node, {node->getConfig()}); Event::publish<Event::NodeAllocation>(node, {node->getConfig()});
@@ -260,13 +289,13 @@ YOGA_EXPORT void YGNodeFree(const YGNodeRef node) {
node->clearChildren(); node->clearChildren();
Event::publish<Event::NodeDeallocation>(node, {node->getConfig()}); Event::publish<Event::NodeDeallocation>(node, {node->getConfig()});
delete node; YGFree(node);
} }
static void YGConfigFreeRecursive(const YGNodeRef root) { static void YGConfigFreeRecursive(const YGNodeRef root) {
if (root->getConfig() != nullptr) { if (root->getConfig() != nullptr) {
gConfigInstanceCount--; gConfigInstanceCount--;
delete root->getConfig(); YGFree(root->getConfig());
} }
// Delete configs recursively for childrens // Delete configs recursively for childrens
for (auto* child : root->getChildren()) { for (auto* child : root->getChildren()) {
@@ -308,16 +337,16 @@ int32_t YGConfigGetInstanceCount(void) {
YOGA_EXPORT YGConfigRef YGConfigNew(void) { YOGA_EXPORT YGConfigRef YGConfigNew(void) {
#ifdef ANDROID #ifdef ANDROID
const YGConfigRef config = new YGConfig(YGAndroidLog); const YGConfigRef config = YGAllocate<YGConfig>(YGAndroidLog);
#else #else
const YGConfigRef config = new YGConfig(YGDefaultLog); const YGConfigRef config = YGAllocate<YGConfig>(YGDefaultLog);
#endif #endif
gConfigInstanceCount++; gConfigInstanceCount++;
return config; return config;
} }
YOGA_EXPORT void YGConfigFree(const YGConfigRef config) { YOGA_EXPORT void YGConfigFree(const YGConfigRef config) {
delete config; YGFree(config);
gConfigInstanceCount--; gConfigInstanceCount--;
} }

View File

@@ -29,6 +29,9 @@ typedef struct YGSize {
float height; float height;
} YGSize; } YGSize;
typedef void* (*YGAllocatorAllocateFunc)(size_t size);
typedef void (*YGAllocatorFreeFunc)(void* memory);
typedef struct YGConfig* YGConfigRef; typedef struct YGConfig* YGConfigRef;
typedef struct YGNode* YGNodeRef; typedef struct YGNode* YGNodeRef;
@@ -53,6 +56,13 @@ typedef int (*YGLogger)(
typedef YGNodeRef ( typedef YGNodeRef (
*YGCloneNodeFunc)(YGNodeRef oldNode, YGNodeRef owner, int childIndex); *YGCloneNodeFunc)(YGNodeRef oldNode, YGNodeRef owner, int childIndex);
// Memory allocation
WIN_EXPORT void YGSetAllocationCallbacks(YGAllocatorAllocateFunc allocFunc, YGAllocatorFreeFunc freeFunc);
WIN_EXPORT void YGGetAllocationCallbacks(YGAllocatorAllocateFunc* allocFunc, YGAllocatorFreeFunc* freeFunc);
WIN_EXPORT void* YGMemoryAllocate(size_t size);
WIN_EXPORT void YGMemoryFree(void* memory);
// YGNode // YGNode
WIN_EXPORT YGNodeRef YGNodeNew(void); WIN_EXPORT YGNodeRef YGNodeNew(void);
WIN_EXPORT YGNodeRef YGNodeNewWithConfig(YGConfigRef config); WIN_EXPORT YGNodeRef YGNodeNewWithConfig(YGConfigRef config);
@@ -363,6 +373,21 @@ YG_EXTERN_C_END
#include <functional> #include <functional>
#include <vector> #include <vector>
#include <type_traits>
// Templated delegates for YGMemoryAllocate & YGMemoryFree, so we don't have to
// cast nor pass in the size of the allocated chunk of memory explicitly.
template<typename T, typename... A>
T* YGAllocate(A&&... arguments) {
auto* memory = reinterpret_cast<T*>(YGMemoryAllocate(sizeof(T)));
new(memory) T(std::forward<A>(arguments)...);
return memory;
}
template<typename T>
void YGFree(T* memory) {
memory->~T();
YGMemoryFree(memory);
}
// Calls f on each node in the tree including the given node argument. // Calls f on each node in the tree including the given node argument.
void YGTraversePreOrder( void YGTraversePreOrder(