Skip to content

Commit bc2139c

Browse files
committed
Add support to C atomics for clang, gcc and msvc.
1 parent b551fe4 commit bc2139c

File tree

14 files changed

+611
-120
lines changed

14 files changed

+611
-120
lines changed

CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ option(OPTION_GIT_HOOKS "Disable git hooks when running in CI/CD." ON)
9494
option(OPTION_FORK_SAFE "Enable fork safety." ON)
9595
option(OPTION_THREAD_SAFE "Enable thread safety." OFF)
9696
option(OPTION_COVERAGE "Enable coverage." OFF)
97+
option(OPTION_MEMORY_TRACKER "Enable memory tracking for reflect data." ON)
9798

9899
# Build type
99100
if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)

cmake/CompileOptions.cmake

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -34,21 +34,30 @@ include(Portability)
3434
# Project options
3535
#
3636

37+
# Test for GNU, Clang or ((Visual Studio C++ or Clang with MSVC backend) and Visual Studio 2022 or superior)
38+
if(("${CMAKE_C_COMPILER_ID}" STREQUAL "GNU") OR
39+
("${CMAKE_C_COMPILER_ID}" STREQUAL "Clang") OR
40+
("${CMAKE_C_COMPILER_ID}" STREQUAL "AppleClang") OR
41+
(
42+
(("${CMAKE_C_COMPILER_ID}" STREQUAL "MSVC") OR
43+
(("${CMAKE_C_COMPILER_ID}" STREQUAL "Clang") AND ("${CMAKE_C_COMPILER_FRONTEND_VARIANT}" STREQUAL "MSVC"))) AND
44+
(MSVC_VERSION GREATER_EQUAL 1930)
45+
)
46+
)
47+
set(C_STANDARD 11) # TODO: Implement support for older standards
48+
else()
49+
set(C_STANDARD 99)
50+
endif()
51+
3752
set(DEFAULT_PROJECT_OPTIONS
3853
DEBUG_POSTFIX "d"
3954
CXX_STANDARD 11
4055
LINKER_LANGUAGE "CXX"
4156
POSITION_INDEPENDENT_CODE ON
4257
CXX_VISIBILITY_PRESET "hidden"
58+
C_STANDARD ${C_STANDARD}
4359
)
4460

45-
if(CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX)
46-
set(DEFAULT_PROJECT_OPTIONS
47-
${DEFAULT_PROJECT_OPTIONS}
48-
C_STANDARD 11 # TODO: Provide support for older standards
49-
)
50-
endif()
51-
5261
#
5362
# Include directories
5463
#
@@ -106,8 +115,15 @@ else()
106115
set(LOG_POLICY_FORMAT_PRETTY_VALUE 0)
107116
endif()
108117

118+
if(OPTION_MEMORY_TRACKER)
119+
set(REFLECT_MEMORY_TRACKER_VALUE 1)
120+
else()
121+
set(REFLECT_MEMORY_TRACKER_VALUE 0)
122+
endif()
123+
109124
set(DEFAULT_COMPILE_DEFINITIONS
110125
LOG_POLICY_FORMAT_PRETTY=${LOG_POLICY_FORMAT_PRETTY_VALUE}
126+
REFLECT_MEMORY_TRACKER=${REFLECT_MEMORY_TRACKER_VALUE}
111127
SYSTEM_${SYSTEM_NAME_UPPER}
112128
${SANITIZER_COMPILE_DEFINITIONS}
113129
)

source/metacall/source/metacall.c

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2217,11 +2217,8 @@ int metacall_destroy(void)
22172217

22182218
metacall_initialize_flag = 1;
22192219

2220-
/* Print stats from functions, classes and objects */
2221-
function_stats_debug();
2222-
class_stats_debug();
2223-
object_stats_debug();
2224-
exception_stats_debug();
2220+
/* Print stats from functions, classes, objects and exceptions */
2221+
reflect_memory_tracker_debug();
22252222

22262223
/* Set to null the plugin extension */
22272224
plugin_extension_handle = NULL;

source/reflect/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ set(headers
4545
${include_path}/reflect_attribute.h
4646
${include_path}/reflect_constructor_decl.h
4747
${include_path}/reflect_constructor.h
48+
${include_path}/reflect_memory_tracker.h
4849
${include_path}/reflect_method_decl.h
4950
${include_path}/reflect_method.h
5051
${include_path}/reflect_class_decl.h
@@ -72,6 +73,7 @@ set(sources
7273
${source_path}/reflect_function.c
7374
${source_path}/reflect_attribute.c
7475
${source_path}/reflect_constructor.c
76+
${source_path}/reflect_memory_tracker.c
7577
${source_path}/reflect_method.c
7678
${source_path}/reflect_class_visibility.c
7779
${source_path}/reflect_class.c

source/reflect/include/reflect/reflect.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,10 @@
3939
#include <reflect/reflect_value_type_id_size.h>
4040
#include <reflect/reflect_value_type_promotion.h>
4141

42+
#ifndef __cplusplus
43+
#include <reflect/reflect_memory_tracker.h>
44+
#endif
45+
4246
#ifdef __cplusplus
4347
extern "C" {
4448
#endif
Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
/*
2+
* Reflect Library by Parra Studios
3+
* A library for provide reflection and metadata representation.
4+
*
5+
* Copyright (C) 2016 - 2022 Vicente Eduardo Ferrer Garcia <[email protected]>
6+
*
7+
* Licensed under the Apache License, Version 2.0 (the "License");
8+
* you may not use this file except in compliance with the License.
9+
* You may obtain a copy of the License at
10+
*
11+
* http://www.apache.org/licenses/LICENSE-2.0
12+
*
13+
* Unless required by applicable law or agreed to in writing, software
14+
* distributed under the License is distributed on an "AS IS" BASIS,
15+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16+
* See the License for the specific language governing permissions and
17+
* limitations under the License.
18+
*
19+
*/
20+
21+
#ifndef REFLECT_MEMORY_TRACKER_H
22+
#define REFLECT_MEMORY_TRACKER_H 1
23+
24+
#include <reflect/reflect_api.h>
25+
26+
#ifdef __cplusplus
27+
extern "C" {
28+
#endif
29+
30+
#if defined(REFLECT_MEMORY_TRACKER) && REFLECT_MEMORY_TRACKER == 1
31+
32+
#include <threading/threading_atomic.h>
33+
34+
#include <format/format_specifier.h>
35+
36+
#include <stdio.h>
37+
38+
#define reflect_memory_tracker(name) \
39+
static struct \
40+
{ \
41+
atomic_uintmax_t allocations; \
42+
atomic_uintmax_t deallocations; \
43+
atomic_uintmax_t increments; \
44+
atomic_uintmax_t decrements; \
45+
} name = { 0, 0, 0, 0 }
46+
47+
#define reflect_memory_tracker_allocation(name) \
48+
atomic_fetch_add_explicit(&name.allocations, 1, memory_order_relaxed)
49+
50+
#define reflect_memory_tracker_deallocation(name) \
51+
atomic_fetch_add_explicit(&name.deallocations, 1, memory_order_relaxed)
52+
53+
#define reflect_memory_tracker_increment(name) \
54+
atomic_fetch_add_explicit(&name.increments, 1, memory_order_relaxed)
55+
56+
#define reflect_memory_tracker_decrement(name) \
57+
atomic_fetch_add_explicit(&name.decrements, 1, memory_order_relaxed)
58+
59+
#if !defined(NDEBUG) || defined(DEBUG) || defined(_DEBUG) || defined(__DEBUG) || defined(__DEBUG__)
60+
#define reflect_memory_tracker_print(name, title) \
61+
do \
62+
{ \
63+
printf("----------------- " title " -----------------\n"); \
64+
printf("Allocations: %" PRIuS "\n", atomic_load_explicit(&name.allocations, memory_order_relaxed)); \
65+
printf("Deallocations: %" PRIuS "\n", atomic_load_explicit(&name.deallocations, memory_order_relaxed)); \
66+
printf("Increments: %" PRIuS "\n", atomic_load_explicit(&name.increments, memory_order_relaxed)); \
67+
printf("Decrements: %" PRIuS "\n", atomic_load_explicit(&name.decrements, memory_order_relaxed)); \
68+
fflush(stdout); \
69+
} while (0)
70+
#else
71+
#define reflect_memory_tracker_print(name, title) \
72+
do \
73+
{ \
74+
uintmax_t allocations = atomic_load_explicit(&name.allocations, memory_order_relaxed); \
75+
uintmax_t deallocations = atomic_load_explicit(&name.deallocations, memory_order_relaxed); \
76+
uintmax_t increments = atomic_load_explicit(&name.increments, memory_order_relaxed); \
77+
uintmax_t decrements = atomic_load_explicit(&name.decrements, memory_order_relaxed); \
78+
/* This comparison is safe to be done like this because it is done once execution has finalized */ \
79+
if (allocations != deallocations || increments != decrements) \
80+
{ \
81+
printf("----------------- " title " -----------------\n"); \
82+
printf("Allocations: %" PRIuS "\n", allocations); \
83+
printf("Deallocations: %" PRIuS "\n", deallocations); \
84+
printf("Increments: %" PRIuS "\n", increments); \
85+
printf("Decrements: %" PRIuS "\n", decrements); \
86+
fflush(stdout); \
87+
} \
88+
} while (0)
89+
#endif
90+
#else
91+
#define reflect_memory_tracker(name) \
92+
typedef char reflect_memory_tracker_disabled
93+
94+
#define reflect_memory_tracker_allocation(name) \
95+
do \
96+
{ \
97+
} while (0)
98+
99+
#define reflect_memory_tracker_deallocation(name) \
100+
do \
101+
{ \
102+
} while (0)
103+
104+
#define reflect_memory_tracker_increment(name) \
105+
do \
106+
{ \
107+
} while (0)
108+
109+
#define reflect_memory_tracker_decrement(name) \
110+
do \
111+
{ \
112+
} while (0)
113+
114+
#define reflect_memory_tracker_print(name, title) \
115+
do \
116+
{ \
117+
} while (0)
118+
#endif
119+
120+
void reflect_memory_tracker_debug(void);
121+
122+
#ifdef __cplusplus
123+
}
124+
#endif
125+
126+
#endif /* REFLECT_MEMORY_TRACKER_H */

source/reflect/source/reflect_class.c

Lines changed: 8 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,9 @@
2727

2828
#include <reflect/reflect_accessor.h>
2929

30-
#include <log/log.h>
30+
#include <reflect/reflect_memory_tracker.h>
3131

32-
#include <threading/threading_atomic.h>
32+
#include <log/log.h>
3333

3434
#include <stdlib.h>
3535
#include <string.h>
@@ -56,13 +56,7 @@ struct class_metadata_iterator_args_type
5656

5757
typedef struct class_metadata_iterator_args_type *class_metadata_iterator_args;
5858

59-
static struct
60-
{
61-
threading_atomic size_t allocations;
62-
threading_atomic size_t deallocations;
63-
threading_atomic size_t increments;
64-
threading_atomic size_t decrements;
65-
} class_stats = { 0, 0, 0, 0 };
59+
reflect_memory_tracker(class_stats);
6660

6761
static value class_metadata_name(klass cls);
6862
static value class_metadata_constructors(klass cls);
@@ -138,7 +132,7 @@ klass class_create(const char *name, enum accessor_type_id accessor, class_impl
138132
}
139133
}
140134

141-
++class_stats.allocations;
135+
reflect_memory_tracker_allocation(class_stats);
142136

143137
return cls;
144138
}
@@ -156,7 +150,7 @@ int class_increment_reference(klass cls)
156150
}
157151

158152
++cls->ref_count;
159-
++class_stats.increments;
153+
reflect_memory_tracker_increment(class_stats);
160154

161155
return 0;
162156
}
@@ -174,7 +168,7 @@ int class_decrement_reference(klass cls)
174168
}
175169

176170
--cls->ref_count;
177-
++class_stats.decrements;
171+
reflect_memory_tracker_decrement(class_stats);
178172

179173
return 0;
180174
}
@@ -837,17 +831,7 @@ void class_constructors_destroy(klass cls)
837831

838832
void class_stats_debug(void)
839833
{
840-
#if !(!defined(NDEBUG) || defined(DEBUG) || defined(_DEBUG) || defined(__DEBUG) || defined(__DEBUG__))
841-
if (class_stats.allocations != class_stats.deallocations || class_stats.increments != class_stats.decrements)
842-
#endif
843-
{
844-
printf("----------------- CLASSES -----------------\n");
845-
printf("Allocations: %" PRIuS "\n", class_stats.allocations);
846-
printf("Deallocations: %" PRIuS "\n", class_stats.deallocations);
847-
printf("Increments: %" PRIuS "\n", class_stats.increments);
848-
printf("Decrements: %" PRIuS "\n", class_stats.decrements);
849-
fflush(stdout);
850-
}
834+
reflect_memory_tracker_print(class_stats, "CLASSES");
851835
}
852836

853837
void class_destroy(klass cls)
@@ -915,7 +899,7 @@ void class_destroy(klass cls)
915899

916900
free(cls);
917901

918-
++class_stats.deallocations;
902+
reflect_memory_tracker_deallocation(class_stats);
919903
}
920904
}
921905
}

0 commit comments

Comments
 (0)