• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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