1b877906bSopenharmony_ci//======================================================================== 2b877906bSopenharmony_ci// Custom heap allocator test 3b877906bSopenharmony_ci// Copyright (c) Camilla Löwy <elmindreda@glfw.org> 4b877906bSopenharmony_ci// 5b877906bSopenharmony_ci// This software is provided 'as-is', without any express or implied 6b877906bSopenharmony_ci// warranty. In no event will the authors be held liable for any damages 7b877906bSopenharmony_ci// arising from the use of this software. 8b877906bSopenharmony_ci// 9b877906bSopenharmony_ci// Permission is granted to anyone to use this software for any purpose, 10b877906bSopenharmony_ci// including commercial applications, and to alter it and redistribute it 11b877906bSopenharmony_ci// freely, subject to the following restrictions: 12b877906bSopenharmony_ci// 13b877906bSopenharmony_ci// 1. The origin of this software must not be misrepresented; you must not 14b877906bSopenharmony_ci// claim that you wrote the original software. If you use this software 15b877906bSopenharmony_ci// in a product, an acknowledgment in the product documentation would 16b877906bSopenharmony_ci// be appreciated but is not required. 17b877906bSopenharmony_ci// 18b877906bSopenharmony_ci// 2. Altered source versions must be plainly marked as such, and must not 19b877906bSopenharmony_ci// be misrepresented as being the original software. 20b877906bSopenharmony_ci// 21b877906bSopenharmony_ci// 3. This notice may not be removed or altered from any source 22b877906bSopenharmony_ci// distribution. 23b877906bSopenharmony_ci// 24b877906bSopenharmony_ci//======================================================================== 25b877906bSopenharmony_ci 26b877906bSopenharmony_ci#define GLAD_GL_IMPLEMENTATION 27b877906bSopenharmony_ci#include <glad/gl.h> 28b877906bSopenharmony_ci#define GLFW_INCLUDE_NONE 29b877906bSopenharmony_ci#include <GLFW/glfw3.h> 30b877906bSopenharmony_ci 31b877906bSopenharmony_ci#include <stdio.h> 32b877906bSopenharmony_ci#include <stdlib.h> 33b877906bSopenharmony_ci#include <assert.h> 34b877906bSopenharmony_ci 35b877906bSopenharmony_ci#define CALL(x) (function_name = #x, x) 36b877906bSopenharmony_cistatic const char* function_name = NULL; 37b877906bSopenharmony_ci 38b877906bSopenharmony_cistruct allocator_stats 39b877906bSopenharmony_ci{ 40b877906bSopenharmony_ci size_t total; 41b877906bSopenharmony_ci size_t current; 42b877906bSopenharmony_ci size_t maximum; 43b877906bSopenharmony_ci}; 44b877906bSopenharmony_ci 45b877906bSopenharmony_cistatic void error_callback(int error, const char* description) 46b877906bSopenharmony_ci{ 47b877906bSopenharmony_ci fprintf(stderr, "Error: %s\n", description); 48b877906bSopenharmony_ci} 49b877906bSopenharmony_ci 50b877906bSopenharmony_cistatic void* allocate(size_t size, void* user) 51b877906bSopenharmony_ci{ 52b877906bSopenharmony_ci struct allocator_stats* stats = user; 53b877906bSopenharmony_ci assert(size > 0); 54b877906bSopenharmony_ci 55b877906bSopenharmony_ci stats->total += size; 56b877906bSopenharmony_ci stats->current += size; 57b877906bSopenharmony_ci if (stats->current > stats->maximum) 58b877906bSopenharmony_ci stats->maximum = stats->current; 59b877906bSopenharmony_ci 60b877906bSopenharmony_ci printf("%s: allocate %zu bytes (current %zu maximum %zu total %zu)\n", 61b877906bSopenharmony_ci function_name, size, stats->current, stats->maximum, stats->total); 62b877906bSopenharmony_ci 63b877906bSopenharmony_ci size_t* real_block = malloc(size + sizeof(size_t)); 64b877906bSopenharmony_ci assert(real_block != NULL); 65b877906bSopenharmony_ci *real_block = size; 66b877906bSopenharmony_ci return real_block + 1; 67b877906bSopenharmony_ci} 68b877906bSopenharmony_ci 69b877906bSopenharmony_cistatic void deallocate(void* block, void* user) 70b877906bSopenharmony_ci{ 71b877906bSopenharmony_ci struct allocator_stats* stats = user; 72b877906bSopenharmony_ci assert(block != NULL); 73b877906bSopenharmony_ci 74b877906bSopenharmony_ci size_t* real_block = (size_t*) block - 1; 75b877906bSopenharmony_ci stats->current -= *real_block; 76b877906bSopenharmony_ci 77b877906bSopenharmony_ci printf("%s: deallocate %zu bytes (current %zu maximum %zu total %zu)\n", 78b877906bSopenharmony_ci function_name, *real_block, stats->current, stats->maximum, stats->total); 79b877906bSopenharmony_ci 80b877906bSopenharmony_ci free(real_block); 81b877906bSopenharmony_ci} 82b877906bSopenharmony_ci 83b877906bSopenharmony_cistatic void* reallocate(void* block, size_t size, void* user) 84b877906bSopenharmony_ci{ 85b877906bSopenharmony_ci struct allocator_stats* stats = user; 86b877906bSopenharmony_ci assert(block != NULL); 87b877906bSopenharmony_ci assert(size > 0); 88b877906bSopenharmony_ci 89b877906bSopenharmony_ci size_t* real_block = (size_t*) block - 1; 90b877906bSopenharmony_ci stats->total += size; 91b877906bSopenharmony_ci stats->current += size - *real_block; 92b877906bSopenharmony_ci if (stats->current > stats->maximum) 93b877906bSopenharmony_ci stats->maximum = stats->current; 94b877906bSopenharmony_ci 95b877906bSopenharmony_ci printf("%s: reallocate %zu bytes to %zu bytes (current %zu maximum %zu total %zu)\n", 96b877906bSopenharmony_ci function_name, *real_block, size, stats->current, stats->maximum, stats->total); 97b877906bSopenharmony_ci 98b877906bSopenharmony_ci real_block = realloc(real_block, size + sizeof(size_t)); 99b877906bSopenharmony_ci assert(real_block != NULL); 100b877906bSopenharmony_ci *real_block = size; 101b877906bSopenharmony_ci return real_block + 1; 102b877906bSopenharmony_ci} 103b877906bSopenharmony_ci 104b877906bSopenharmony_ciint main(void) 105b877906bSopenharmony_ci{ 106b877906bSopenharmony_ci struct allocator_stats stats = {0}; 107b877906bSopenharmony_ci const GLFWallocator allocator = 108b877906bSopenharmony_ci { 109b877906bSopenharmony_ci .allocate = allocate, 110b877906bSopenharmony_ci .deallocate = deallocate, 111b877906bSopenharmony_ci .reallocate = reallocate, 112b877906bSopenharmony_ci .user = &stats 113b877906bSopenharmony_ci }; 114b877906bSopenharmony_ci 115b877906bSopenharmony_ci glfwSetErrorCallback(error_callback); 116b877906bSopenharmony_ci glfwInitAllocator(&allocator); 117b877906bSopenharmony_ci 118b877906bSopenharmony_ci if (!CALL(glfwInit)()) 119b877906bSopenharmony_ci exit(EXIT_FAILURE); 120b877906bSopenharmony_ci 121b877906bSopenharmony_ci GLFWwindow* window = CALL(glfwCreateWindow)(400, 400, "Custom allocator test", NULL, NULL); 122b877906bSopenharmony_ci if (!window) 123b877906bSopenharmony_ci { 124b877906bSopenharmony_ci glfwTerminate(); 125b877906bSopenharmony_ci exit(EXIT_FAILURE); 126b877906bSopenharmony_ci } 127b877906bSopenharmony_ci 128b877906bSopenharmony_ci CALL(glfwMakeContextCurrent)(window); 129b877906bSopenharmony_ci gladLoadGL(glfwGetProcAddress); 130b877906bSopenharmony_ci CALL(glfwSwapInterval)(1); 131b877906bSopenharmony_ci 132b877906bSopenharmony_ci while (!CALL(glfwWindowShouldClose)(window)) 133b877906bSopenharmony_ci { 134b877906bSopenharmony_ci glClear(GL_COLOR_BUFFER_BIT); 135b877906bSopenharmony_ci CALL(glfwSwapBuffers)(window); 136b877906bSopenharmony_ci CALL(glfwWaitEvents)(); 137b877906bSopenharmony_ci } 138b877906bSopenharmony_ci 139b877906bSopenharmony_ci CALL(glfwTerminate)(); 140b877906bSopenharmony_ci exit(EXIT_SUCCESS); 141b877906bSopenharmony_ci} 142b877906bSopenharmony_ci 143