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