Home | History | Annotate | Line # | Download | only in base
      1 /*
      2  * Copyright (c) 2021-2023 Apple Inc. All rights reserved.
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *     https://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #ifndef REF_COUNT_H
     18 #define REF_COUNT_H
     19 
     20 //======================================================================================================================
     21 // MARK: - Headers
     22 
     23 //#include "dnssec_common.h"
     24 #include <stdbool.h>
     25 #include <stdint.h>
     26 #include <stddef.h>	// For offsetof().
     27 
     28 #include "general.h"
     29 #include "nullability.h"
     30 #include "dns_assert_macros.h"
     31 
     32 //======================================================================================================================
     33 // MARK: - General Object Helpers
     34 
     35 #define OBJECT_TYPEDEF_OPAQUE_POINTER(NAME) typedef struct NAME ## _s * NAME ## _t
     36 
     37 // Check if structure `struct <NAME>_s` starts with structure `struct <BASE_NAME>_s <BASE_NAME>;` as the first member.
     38 #define OBJECT_BASE_CHECK(NAME, BASE_NAME) 															\
     39 	check_compile_time(offsetof(struct NAME ## _s, base) == 0);										\
     40 	check_compile_time(sizeof(((struct NAME ## _s *)0)->base) == sizeof(struct BASE_NAME ## _s));	\
     41 	extern int8_t _obj_base_type_check[sizeof(&(((NAME ## _t)0)->base) == ((BASE_NAME ## _t)0))]	\
     42 
     43 #ifndef STRUCT_PTR_DECLARE
     44 	#define STRUCT_PTR_DECLARE(STRUCT_NAME) struct STRUCT_NAME ## _s * NULLABLE STRUCT_NAME
     45 #endif
     46 
     47 #ifndef STRUCT_ARRAY_PTR_DECLARE
     48 	#define STRUCT_ARRAY_PTR_DECLARE(STRUCT_NAME) struct STRUCT_NAME ## _s * NULLABLE * NULLABLE STRUCT_NAME ## s
     49 #endif
     50 
     51 typedef enum {
     52 	compare_result_less		= -1,
     53 	compare_result_equal	= 0,
     54 	compare_result_greater	= 1,
     55 	compare_result_notequal,	// Can ensure that the objects being compared are not equal. Do not know about the exact order.
     56 	compare_result_unknown,		// Unable to determine the comparison result.
     57 } compare_result_t;
     58 
     59 typedef enum {
     60 	sort_order_ascending,
     61 	sort_order_descending
     62 } sort_order_t;
     63 
     64 //======================================================================================================================
     65 // MARK: - Reference Count Object Helper Macros
     66 
     67 // The macros below provide a way to define a reference counted object that comes with comparator and finalizer.
     68 // To define a new reference counted object:
     69 // 1. In the definition of the `ref_count_obj_any_t`, add `REF_COUNT_OBJECT_DECLARE_SUPPORTED_FAMILY(<object family name>);`
     70 //	  to declare that the object family supports reference count and all the methods provided by `ref_count.h` can be
     71 //	  used by the object family.
     72 // 2. Create a header/source file for the object family, define the retain method, release method and compare method for
     73 //	  the object family. This step ensures that all the objects under the same family can be retained, released and
     74 //	  compared, without having to call the underlying ref_count object base. This provides an additional layer of type
     75 //	  check.
     76 // 3. In the definition of the `ref_count_obj_any_t`, add `REF_COUNT_OBJECT_DECLARE_SUPPORTED_OBJECT(<object family name>,
     77 //	  <object type name>);`. This step ensures that this new reference counted object supports the comparator and the
     78 //	  finalizer defined by `ref_count.h`.
     79 // 4. Put `REF_COUNT_OBJECT_DEFINE_FULL(<object family name>, <object type name>);` in the .c file of the object.
     80 // 5. Define a structure with name of `struct <object family name>_<object type name>_s` in the .c file of the object.
     81 //	  The structure should start with `struct ref_count_obj_s	base;` so that it can have reference count and object
     82 //	  property.
     83 // 6. Implement the comparator and the finalizer in the .c file of the object.
     84 //
     85 // Note: If an object family has been defined previously, start from step 3.
     86 
     87 // Declare a initializer for the reference counted object.
     88 #define REF_COUNT_OBJECT_DECLARE_INITIALIZER(FAMILY_NAME, NAME)									\
     89 	static void																					\
     90 	_ ## FAMILY_NAME ## _ ## NAME ## _initialize(FAMILY_NAME ## _ ## NAME ## _t NONNULL object)
     91 
     92 //======================================================================================================================
     93 
     94 
     95 // Declare a comparator for the reference counted object.
     96 #define REF_COUNT_OBJECT_DECLARE_COMPARATOR(FAMILY_NAME, NAME)									\
     97 	static compare_result_t																		\
     98 	_ ## FAMILY_NAME ## _ ## NAME ## _compare(FAMILY_NAME ## _ ## NAME ## _t NONNULL object1,	\
     99 											  FAMILY_NAME ## _ ## NAME ## _t NONNULL object2,	\
    100 											  bool check_equality_only)
    101 
    102 //======================================================================================================================
    103 
    104 // Declare a finalizer for the reference counted object.
    105 #define REF_COUNT_OBJECT_DECLARE_FINALIZER(FAMILY_NAME, NAME)									\
    106 	static void																					\
    107 	_ ## FAMILY_NAME ## _ ## NAME ## _finalize(FAMILY_NAME ## _ ## NAME ## _t NONNULL object)
    108 
    109 //======================================================================================================================
    110 
    111 // Define a New() function for the reference count object to allocate the memory and initialize the memory.
    112 #define REF_COUNT_OBJECT_DEFINE_NEW_FUNC(FAMILY_NAME, NAME)									\
    113 	static FAMILY_NAME ## _ ## NAME ## _t													\
    114 	_ ## FAMILY_NAME ## _ ## NAME ## _new(void)												\
    115 	{																						\
    116 		const FAMILY_NAME ## _ ## NAME ## _t obj = (FAMILY_NAME ## _ ## NAME ## _t)ref_count_obj_alloc(sizeof(*obj));\
    117 		if (obj == NULL) {																	\
    118 			return NULL;																	\
    119 		}																					\
    120 																							\
    121 		ref_count_obj_init(obj, &_ ## FAMILY_NAME ## _ ## NAME ## _kind);					\
    122 		ref_count_obj_retain(obj);															\
    123 		return obj;																			\
    124 	}																						\
    125 	extern int8_t _dummy_variable_to_enforce_semicolon
    126 
    127 //======================================================================================================================
    128 
    129 // Define the kind instance of the reference count object.
    130 #define REF_COUNT_OBJECT_DEFINE_KIND_INSTANCE_BASIC(FAMILY_NAME, NAME, ...)				\
    131 	const struct ref_count_kind_s _ ## FAMILY_NAME ## _ ## NAME ## _kind = { 			\
    132 		MDNS_CLANG_IGNORE_INCOMPATIBLE_FUNCTION_POINTER_TYPES_STRICT_WARNING_BEGIN()	\
    133 		.superkind	= &ref_count_kind,													\
    134 		.name		= # FAMILY_NAME "_" # NAME,											\
    135 		.finalize	= _ ## FAMILY_NAME ## _ ## NAME ## _finalize,						\
    136 		__VA_ARGS__																		\
    137 		MDNS_CLANG_IGNORE_INCOMPATIBLE_FUNCTION_POINTER_TYPES_STRICT_WARNING_END()		\
    138 	};																					\
    139 	OBJECT_BASE_CHECK(FAMILY_NAME ## _ ## NAME, ref_count_obj)
    140 
    141 #define REF_COUNT_OBJECT_DEFINE_KIND_INSTANCE(FAMILY_NAME, NAME)				\
    142 	REF_COUNT_OBJECT_DEFINE_KIND_INSTANCE_BASIC(FAMILY_NAME, NAME,				\
    143 		.compare	= _ ## FAMILY_NAME ## _ ## NAME ## _compare,				\
    144 	)
    145 
    146 #define REF_COUNT_OBJECT_DEFINE_KIND_INSTANCE_WITH_INIT(FAMILY_NAME, NAME)		\
    147 	REF_COUNT_OBJECT_DEFINE_KIND_INSTANCE_BASIC(FAMILY_NAME, NAME,				\
    148 		.init = _ ## FAMILY_NAME ## _ ## NAME ## _initialize					\
    149 	)
    150 
    151 //======================================================================================================================
    152 
    153 // Define a reference count enabled object.
    154 #define REF_COUNT_OBJECT_DEFINE_FULL(FAMILY_NAME, NAME)			\
    155 	REF_COUNT_OBJECT_DECLARE_COMPARATOR(FAMILY_NAME, NAME);		\
    156 	REF_COUNT_OBJECT_DECLARE_FINALIZER(FAMILY_NAME, NAME);		\
    157 	REF_COUNT_OBJECT_DEFINE_KIND_INSTANCE(FAMILY_NAME, NAME);	\
    158 	REF_COUNT_OBJECT_DEFINE_NEW_FUNC(FAMILY_NAME, NAME)
    159 
    160 #define REF_COUNT_OBJECT_DEFINE_WITH_INIT_WITHOUT_COMPARATOR(FAMILY_NAME, NAME)	\
    161 	REF_COUNT_OBJECT_DECLARE_INITIALIZER(FAMILY_NAME, NAME);					\
    162 	REF_COUNT_OBJECT_DECLARE_FINALIZER(FAMILY_NAME, NAME);						\
    163 	REF_COUNT_OBJECT_DEFINE_KIND_INSTANCE_WITH_INIT(FAMILY_NAME, NAME);			\
    164 	REF_COUNT_OBJECT_DEFINE_NEW_FUNC(FAMILY_NAME, NAME)
    165 
    166 
    167 //======================================================================================================================
    168 // MARK: - Subkind of Reference Counted Object Helper Macros
    169 
    170 // The macros below provide a way to define an object that is a subkind of the reference count object that is defined by
    171 // the macros above.
    172 
    173 // Define a new kind type for the reference count object so that its subkind can reference it. `...` are the additional
    174 // members needed for the kind type.
    175 // This is the way how the subkind know what super kind it has.
    176 #define REF_COUNT_OBJECT_DEFINE_KIND_TYPE_FOR_SUBKIND(FAMILY_NAME, NAME, ...)							\
    177 	typedef const struct FAMILY_NAME ## _ ## NAME ## _kind_s *	FAMILY_NAME ## _ ## NAME ## _kind_t;	\
    178 	struct FAMILY_NAME ## _ ## NAME ## _kind_s {														\
    179 		struct ref_count_kind_s	base;																	\
    180 		FAMILY_NAME ## _ ## NAME ## _init_fields_f NONNULL FAMILY_NAME ## _ ## NAME ## _init_fields;	\
    181 		__VA_ARGS__																						\
    182 	};																									\
    183 	OBJECT_BASE_CHECK(FAMILY_NAME ## _ ## NAME ## _kind, ref_count_kind);								\
    184 	extern const struct ref_count_kind_s _ ## FAMILY_NAME ## _ ## NAME ## _kind
    185 
    186 //======================================================================================================================
    187 
    188 // Define the kind instance for the subkind of the reference count object. The reference count object has to exist
    189 // before its subkind can be defined. There are four variations of the helper:
    190 // 1. REF_COUNT_OBJECT_SUBKIND_DEFINE_KIND_INSTANCE_ABSTRUCT: the subkind does not need to implement comparator and finalizer.
    191 // 2. REF_COUNT_OBJECT_SUBKIND_DEFINE_KIND_INSTANCE_WITHOUT_FINALIZER: the subkind does not need to implement finalizer,
    192 //	  but it needs to implement comparator.
    193 // 3. REF_COUNT_OBJECT_SUBKIND_DEFINE_KIND_INSTANCE_WITHOUT_COMPARATOR: the subkind does not need to implement
    194 //	  comparator, but it needs to implement finalizer.
    195 // 4. REF_COUNT_OBJECT_SUBKIND_DEFINE_KIND_INSTANCE_FULL: the subkind needs to implement both comparator and finalizer.
    196 //
    197 // No comparator subkind use case: it means that the super kind of the subkind already has a comparator and no more
    198 // specific comparator needed.
    199 // No finalizer subkind use case: it means that the subkind does not allocate new memory for its new member when doing
    200 // member initialization. Therefore, there is no need for such subkind to define a finalizer that does nothing.
    201 
    202 #define REF_COUNT_OBJECT_SUBKIND_DEFINE_KIND_INSTANCE_ABSTRUCT(FAMILY_NAME, SUPER, NAME, ...)					\
    203 	const struct FAMILY_NAME ## _ ## SUPER ## _kind_s _ ## FAMILY_NAME ## _ ## SUPER ## _ ## NAME ## _kind = {	\
    204 		MDNS_CLANG_IGNORE_INCOMPATIBLE_FUNCTION_POINTER_TYPES_STRICT_WARNING_BEGIN()							\
    205 		.base = {																								\
    206 			.superkind	= &_ ## FAMILY_NAME ## _ ## SUPER ## _kind,												\
    207 			.name 		= # FAMILY_NAME "_" # SUPER "_" # NAME,													\
    208 		},																										\
    209 		.FAMILY_NAME ## _ ## SUPER ## _init_fields = FAMILY_NAME ## _ ## SUPER ## _init_fields,					\
    210 		__VA_ARGS__																								\
    211 		MDNS_CLANG_IGNORE_INCOMPATIBLE_FUNCTION_POINTER_TYPES_STRICT_WARNING_END()								\
    212 	};																											\
    213 	OBJECT_BASE_CHECK(FAMILY_NAME ## _ ## SUPER ## _ ## NAME, FAMILY_NAME ## _ ## SUPER)
    214 
    215 #define REF_COUNT_OBJECT_SUBKIND_DEFINE_KIND_INSTANCE_WITHOUT_FINALIZER(FAMILY_NAME, SUPER, NAME, ...)			\
    216 	const struct FAMILY_NAME ## _ ## SUPER ## _kind_s _ ## FAMILY_NAME ## _ ## SUPER ## _ ## NAME ## _kind = {	\
    217 		.base = {																								\
    218 			.superkind	= &_ ## FAMILY_NAME ## _ ## SUPER ## _kind,												\
    219 			.name 		= # FAMILY_NAME "_" # SUPER "_" # NAME,													\
    220 			.compare	= _ ## FAMILY_NAME ## _ ## SUPER ## _ ## NAME ## _compare,								\
    221 		},																										\
    222 		.FAMILY_NAME ## _ ## SUPER ## _init_fields = FAMILY_NAME ## _ ## SUPER ## _init_fields,					\
    223 		__VA_ARGS__																								\
    224 	};																											\
    225 	OBJECT_BASE_CHECK(FAMILY_NAME ## _ ## SUPER ## _ ## NAME, FAMILY_NAME ## _ ## SUPER)
    226 
    227 #define REF_COUNT_OBJECT_SUBKIND_DEFINE_KIND_INSTANCE_WITHOUT_COMPARATOR(FAMILY_NAME, SUPER, NAME, ...)			\
    228 	const struct FAMILY_NAME ## _ ## SUPER ## _kind_s _ ## FAMILY_NAME ## _ ## SUPER ## _ ## NAME ## _kind = {	\
    229 		MDNS_CLANG_IGNORE_INCOMPATIBLE_FUNCTION_POINTER_TYPES_STRICT_WARNING_BEGIN()							\
    230 		.base = {																								\
    231 			.superkind	= &_ ## FAMILY_NAME ## _ ## SUPER ## _kind,												\
    232 			.name 		= # FAMILY_NAME "_" # SUPER "_" # NAME,													\
    233 			.finalize	= _ ## FAMILY_NAME ## _ ## SUPER ## _ ## NAME ## _finalize								\
    234 		},																										\
    235 		.FAMILY_NAME ## _ ## SUPER ## _init_fields = FAMILY_NAME ## _ ## SUPER ## _init_fields,					\
    236 		__VA_ARGS__																								\
    237 		MDNS_CLANG_IGNORE_INCOMPATIBLE_FUNCTION_POINTER_TYPES_STRICT_WARNING_END()								\
    238 	};																											\
    239 	OBJECT_BASE_CHECK(FAMILY_NAME ## _ ## SUPER ## _ ## NAME, FAMILY_NAME ## _ ## SUPER)
    240 
    241 #define REF_COUNT_OBJECT_SUBKIND_DEFINE_KIND_INSTANCE_FULL(FAMILY_NAME, SUPER, NAME, ...)						\
    242 	const struct FAMILY_NAME ## _ ## SUPER ## _kind_s _ ## FAMILY_NAME ## _ ## SUPER ## _ ## NAME ## _kind = {	\
    243 		.base = {																								\
    244 			MDNS_CLANG_IGNORE_INCOMPATIBLE_FUNCTION_POINTER_TYPES_STRICT_WARNING_BEGIN()						\
    245 			.superkind	= &_ ## FAMILY_NAME ## _ ## SUPER ## _kind,												\
    246 			.name 		= # FAMILY_NAME "_" # SUPER "_" # NAME,													\
    247 			.compare	= _ ## FAMILY_NAME ## _ ## SUPER ## _ ## NAME ## _compare,								\
    248 			.finalize	= _ ## FAMILY_NAME ## _ ## SUPER ## _ ## NAME ## _finalize								\
    249 			MDNS_CLANG_IGNORE_INCOMPATIBLE_FUNCTION_POINTER_TYPES_STRICT_WARNING_END()							\
    250 		},																										\
    251 		.FAMILY_NAME ## _ ## SUPER ## _init_fields = FAMILY_NAME ## _ ## SUPER ## _init_fields,					\
    252 		__VA_ARGS__																								\
    253 	};																											\
    254 	OBJECT_BASE_CHECK(FAMILY_NAME ## _ ## SUPER ## _ ## NAME, FAMILY_NAME ## _ ## SUPER)
    255 
    256 //======================================================================================================================
    257 
    258 // Define a New() function for the subkind of reference count object to allocate the memory and initialize the memory.
    259 #define REF_COUNT_OBJECT_SUBKIND_DEFINE_NEW_FUNC(FAMILY_NAME, SUPER, NAME)						\
    260 	static FAMILY_NAME ## _ ## SUPER ## _ ## NAME ## _t											\
    261 	_ ## FAMILY_NAME ## _ ## SUPER ## _ ## NAME ## _new(void)									\
    262 	{																							\
    263 		const FAMILY_NAME ## _ ## SUPER ## _ ## NAME ## _t obj = (FAMILY_NAME ## _ ## SUPER ## _ ## NAME ## _t)ref_count_obj_alloc(sizeof(*obj));\
    264 		if (obj == NULL) {																		\
    265 			return NULL;																		\
    266 		}																						\
    267 																								\
    268 		ref_count_obj_init(obj, &_ ## FAMILY_NAME ## _ ## SUPER ## _ ## NAME ## _kind.base);	\
    269 		ref_count_obj_retain(obj);																\
    270 		return obj;																				\
    271 	}																							\
    272 	extern int8_t _dummy_variable_to_enforce_semicolon
    273 
    274 //======================================================================================================================
    275 
    276 // Define a subkind object of the reference counted object, based on whether the subkind needs the comparator and
    277 // the finalizer. `...` are the additional member that the kind type of reference counted object needs to initialize
    278 // for this subkind.
    279 #define REF_COUNT_OBJECT_SUBKIND_DEFINE_FULL(FAMILY_NAME, SUPER, NAME, ...)						\
    280 	REF_COUNT_OBJECT_DECLARE_COMPARATOR(FAMILY_NAME, SUPER ## _ ## NAME);						\
    281 	REF_COUNT_OBJECT_DECLARE_FINALIZER(FAMILY_NAME, SUPER ## _ ## NAME);						\
    282 	REF_COUNT_OBJECT_SUBKIND_DEFINE_KIND_INSTANCE_FULL(FAMILY_NAME, SUPER, NAME, __VA_ARGS__);	\
    283 	REF_COUNT_OBJECT_SUBKIND_DEFINE_NEW_FUNC(FAMILY_NAME, SUPER, NAME)
    284 
    285 #define REF_COUNT_OBJECT_SUBKIND_DEFINE_WITHOUT_COMPARATOR(FAMILY_NAME, SUPER, NAME, ...)						\
    286 	REF_COUNT_OBJECT_DECLARE_FINALIZER(FAMILY_NAME, SUPER ## _ ## NAME);										\
    287 	REF_COUNT_OBJECT_SUBKIND_DEFINE_KIND_INSTANCE_WITHOUT_COMPARATOR(FAMILY_NAME, SUPER, NAME, __VA_ARGS__);	\
    288 	REF_COUNT_OBJECT_SUBKIND_DEFINE_NEW_FUNC(FAMILY_NAME, SUPER, NAME)
    289 
    290 #define REF_COUNT_OBJECT_SUBKIND_DEFINE_WITHOUT_FINALIZER(FAMILY_NAME, SUPER, NAME, ...)						\
    291 	REF_COUNT_OBJECT_DECLARE_COMPARATOR(FAMILY_NAME, SUPER ## _ ## NAME);										\
    292 	REF_COUNT_OBJECT_SUBKIND_DEFINE_KIND_INSTANCE_WITHOUT_FINALIZER(FAMILY_NAME, SUPER, NAME, __VA_ARGS__);		\
    293 	REF_COUNT_OBJECT_SUBKIND_DEFINE_NEW_FUNC(FAMILY_NAME, SUPER, NAME)
    294 
    295 #define REF_COUNT_OBJECT_SUBKIND_DEFINE_ABSTRUCT(FAMILY_NAME, SUPER, NAME, ...)						\
    296 	REF_COUNT_OBJECT_SUBKIND_DEFINE_KIND_INSTANCE_ABSTRUCT(FAMILY_NAME, SUPER, NAME, __VA_ARGS__);	\
    297 	REF_COUNT_OBJECT_SUBKIND_DEFINE_NEW_FUNC(FAMILY_NAME, SUPER, NAME)
    298 
    299 //======================================================================================================================
    300 // MARK: - Reference Counted Object Declaration
    301 
    302 #define REF_COUNT_OBJECT_DECLARE_SUPPORTED_FAMILY(FAMILY_NAME) 							STRUCT_PTR_DECLARE(FAMILY_NAME)
    303 #define REF_COUNT_OBJECT_DECLARE_SUPPORTED_OBJECT(FAMILY_NAME, NAME)					STRUCT_PTR_DECLARE(FAMILY_NAME ## _ ## NAME)
    304 #define REF_COUNT_OBJECT_DECLARE_SUPPORTED_OBJECT_SUBKIND(FAMILY_NAME, SUPER, NAME)		REF_COUNT_OBJECT_DECLARE_SUPPORTED_OBJECT(FAMILY_NAME, SUPER ## _ ## NAME)
    305 
    306 #define REF_COUNT_OBJECT_ARRAY_DECLARE_SUPPORTED_FAMILY(FAMILY_NAME) 						STRUCT_ARRAY_PTR_DECLARE(FAMILY_NAME)
    307 #define REF_COUNT_OBJECT_ARRAY_DECLARE_SUPPORTED_OBJECT(FAMILY_NAME, NAME)					STRUCT_ARRAY_PTR_DECLARE(FAMILY_NAME ## _ ## NAME)
    308 #define REF_COUNT_OBJECT_ARRAY_DECLARE_SUPPORTED_OBJECT_SUBKIND(FAMILY_NAME, SUPER, NAME)	REF_COUNT_OBJECT_ARRAY_DECLARE_SUPPORTED_OBJECT(FAMILY_NAME, SUPER ## _ ## NAME)
    309 
    310 typedef union {
    311 	// The universal reference count enabled object.
    312 	STRUCT_PTR_DECLARE(ref_count_obj);
    313 
    314 	// -------- The DNS Object families --------
    315 	REF_COUNT_OBJECT_DECLARE_SUPPORTED_FAMILY(dns_obj);
    316 	REF_COUNT_OBJECT_DECLARE_SUPPORTED_OBJECT(dns_obj, domain_name);
    317 	REF_COUNT_OBJECT_DECLARE_SUPPORTED_OBJECT(dns_obj, rr);
    318 	REF_COUNT_OBJECT_DECLARE_SUPPORTED_OBJECT_SUBKIND(dns_obj, rr, cname);	// CNAME RR
    319 	REF_COUNT_OBJECT_DECLARE_SUPPORTED_OBJECT_SUBKIND(dns_obj, rr, soa);	// SOA RR
    320 	REF_COUNT_OBJECT_DECLARE_SUPPORTED_OBJECT_SUBKIND(dns_obj, rr, srv);	// SRV RR
    321 	REF_COUNT_OBJECT_DECLARE_SUPPORTED_OBJECT_SUBKIND(dns_obj, rr, nsec);	// NSEC RR
    322 	REF_COUNT_OBJECT_DECLARE_SUPPORTED_OBJECT_SUBKIND(dns_obj, rr, ds);		// DS RR
    323 	REF_COUNT_OBJECT_DECLARE_SUPPORTED_OBJECT_SUBKIND(dns_obj, rr, rrsig);	// RRSIG RR
    324 	REF_COUNT_OBJECT_DECLARE_SUPPORTED_OBJECT_SUBKIND(dns_obj, rr, dnskey);	// DNSKEY RR
    325 	REF_COUNT_OBJECT_DECLARE_SUPPORTED_OBJECT_SUBKIND(dns_obj, rr, nsec3);	// NSEC3 RR
    326 
    327 	// -------- The DNSSEC Object families --------
    328 	REF_COUNT_OBJECT_DECLARE_SUPPORTED_FAMILY(dnssec_obj);
    329 	// The validation task manager object in the DNSSEC Object families.
    330 	REF_COUNT_OBJECT_DECLARE_SUPPORTED_OBJECT(dnssec_obj, validation_manager);
    331 	// The callback context object in the DNSSEC Object families.
    332 	REF_COUNT_OBJECT_DECLARE_SUPPORTED_OBJECT(dnssec_obj, context);
    333 	// The trust anchor object in the DNSSEC Object families.
    334 	REF_COUNT_OBJECT_DECLARE_SUPPORTED_OBJECT(dnssec_obj, trust_anchor);
    335 	// The trust anchor manager object in the DNSSEC Object families.
    336 	REF_COUNT_OBJECT_DECLARE_SUPPORTED_OBJECT(dnssec_obj, trust_anchor_manager);
    337 	// The domain name object in the DNSSEC Object families.
    338 	REF_COUNT_OBJECT_DECLARE_SUPPORTED_OBJECT(dnssec_obj, domain_name);
    339 	// The resource record set object in the DNSSEC Object families.
    340 	REF_COUNT_OBJECT_DECLARE_SUPPORTED_OBJECT(dnssec_obj, rrset);
    341 	// The resource record validator object in the DNSSEC Object families.
    342 	REF_COUNT_OBJECT_DECLARE_SUPPORTED_OBJECT(dnssec_obj, rr_validator);
    343 	// The denial of existence object in the DNSSEC Object families.
    344 	REF_COUNT_OBJECT_DECLARE_SUPPORTED_OBJECT(dnssec_obj, denial_of_existence);
    345 	// The resource record and its subkind object in the DNSSEC Object families.
    346 	REF_COUNT_OBJECT_DECLARE_SUPPORTED_OBJECT(dnssec_obj, rr);
    347 	REF_COUNT_OBJECT_DECLARE_SUPPORTED_OBJECT_SUBKIND(dnssec_obj, rr, cname);	// CNAME RR
    348 	REF_COUNT_OBJECT_DECLARE_SUPPORTED_OBJECT_SUBKIND(dnssec_obj, rr, soa);		// SOA RR
    349 	REF_COUNT_OBJECT_DECLARE_SUPPORTED_OBJECT_SUBKIND(dnssec_obj, rr, srv);		// SRV RR
    350 	REF_COUNT_OBJECT_DECLARE_SUPPORTED_OBJECT_SUBKIND(dnssec_obj, rr, nsec);	// NSEC RR
    351 	REF_COUNT_OBJECT_DECLARE_SUPPORTED_OBJECT_SUBKIND(dnssec_obj, rr, ds);		// DS RR
    352 	REF_COUNT_OBJECT_DECLARE_SUPPORTED_OBJECT_SUBKIND(dnssec_obj, rr, rrsig);	// RRSIG RR
    353 	REF_COUNT_OBJECT_DECLARE_SUPPORTED_OBJECT_SUBKIND(dnssec_obj, rr, dnskey);	// DNSKEY RR
    354 	REF_COUNT_OBJECT_DECLARE_SUPPORTED_OBJECT_SUBKIND(dnssec_obj, rr, nsec3);	// NSEC3 RR
    355 
    356 	REF_COUNT_OBJECT_DECLARE_SUPPORTED_OBJECT(dnssec_obj, resource_record_member);
    357 	REF_COUNT_OBJECT_DECLARE_SUPPORTED_OBJECT(dnssec_obj, dns_question_member);
    358 
    359 	// -------- The DNS Push Object families --------
    360 	REF_COUNT_OBJECT_DECLARE_SUPPORTED_FAMILY(dns_push_obj);
    361 	REF_COUNT_OBJECT_DECLARE_SUPPORTED_OBJECT(dns_push_obj, context);
    362 	REF_COUNT_OBJECT_DECLARE_SUPPORTED_OBJECT(dns_push_obj, discovered_service_manager);
    363 	REF_COUNT_OBJECT_DECLARE_SUPPORTED_OBJECT(dns_push_obj, dns_question_member);
    364 	REF_COUNT_OBJECT_DECLARE_SUPPORTED_OBJECT(dns_push_obj, resource_record_member);
    365 
    366 } ref_count_obj_any_t __attribute__((__transparent_union__));
    367 
    368 typedef union {
    369 	// The universal reference count enabled objects array.
    370 	STRUCT_ARRAY_PTR_DECLARE(ref_count_obj);
    371 
    372 	// -------- The DNSSEC Object array families --------
    373 	REF_COUNT_OBJECT_ARRAY_DECLARE_SUPPORTED_FAMILY(dnssec_obj);
    374 	REF_COUNT_OBJECT_ARRAY_DECLARE_SUPPORTED_OBJECT(dnssec_obj, domain_name);			// domain names array
    375 
    376 	REF_COUNT_OBJECT_ARRAY_DECLARE_SUPPORTED_OBJECT(dnssec_obj, rr);					// RRs array
    377 	REF_COUNT_OBJECT_ARRAY_DECLARE_SUPPORTED_OBJECT_SUBKIND(dnssec_obj, rr, nsec);		// NSEC RRs array
    378 	REF_COUNT_OBJECT_ARRAY_DECLARE_SUPPORTED_OBJECT_SUBKIND(dnssec_obj, rr, dnskey);	// DNSKEY RRs array
    379 	REF_COUNT_OBJECT_ARRAY_DECLARE_SUPPORTED_OBJECT_SUBKIND(dnssec_obj, rr, nsec3);		// NSEC3 RRs array
    380 
    381 	// -------- The DNS Object families --------
    382 	REF_COUNT_OBJECT_ARRAY_DECLARE_SUPPORTED_FAMILY(dns_obj);
    383 	REF_COUNT_OBJECT_ARRAY_DECLARE_SUPPORTED_OBJECT(dns_obj, domain_name);				// domain names array
    384 
    385 } ref_count_objs_any_t __attribute__((__transparent_union__));
    386 
    387 //======================================================================================================================
    388 // MARK: - The Reference Count Structure Base
    389 
    390 typedef void
    391 (*ref_count_init_f)(ref_count_obj_any_t object);
    392 
    393 typedef compare_result_t
    394 (*ref_count_compare_f)(ref_count_obj_any_t object1, ref_count_obj_any_t object2, bool check_equality_only);
    395 
    396 typedef void
    397 (*ref_count_finalize_f)(ref_count_obj_any_t object);
    398 
    399 typedef const struct ref_count_kind_s *ref_count_kind_t;
    400 struct ref_count_kind_s {
    401 	ref_count_kind_t NULLABLE		superkind;	// Points to the kind instance of the super kind.
    402 	const char * NONNULL			name;		// The name of the current kind. Just for information purpose.
    403 	ref_count_init_f NULLABLE		init;		// The memory initialization method, most of time it will be NULL.
    404 	ref_count_compare_f NULLABLE	compare;	// The comparator of the kind.
    405 	ref_count_finalize_f NULLABLE	finalize;	// The finalizer of the kind.
    406 };
    407 // Note the difference between memory initialization and member(field) initialization, memory initialization will
    408 // initialize the allocated memory to a default value, for example, zero. However, member(field) initialization will
    409 // initialize the specific object's member to a meaningful value. Most of time, memory initialization is unnecessary
    410 // since we are using calloc() to reset the allocated memory to zero, the memory initialization has been finished and no
    411 // need to explicitly define an initializer. However, under some cases where zero is a meaningful value, for example,
    412 // socket value 0. We have to explicitly define the memory initialization method so that the member can be set to an
    413 // invalid value, such as -1 for socket. We need the member to have a INVALID value because the finalizer needs to know
    414 // if it needs to do some clean up. If the member has an INVALID value, the finalizer does not need to free any resource
    415 // possibly related to it. This allow us to release the object immediately after allocating memory for it, even before
    416 // initializing its member. (the member initialization).
    417 
    418 extern const struct ref_count_kind_s ref_count_kind; // ref_count_kind is defined in ref_count.c
    419 
    420 typedef struct ref_count_obj_s * ref_count_obj_t;
    421 
    422 struct ref_count_obj_s {
    423 	uint32_t					ref_count;
    424 	ref_count_kind_t NONNULL	kind;
    425 };
    426 
    427 //======================================================================================================================
    428 // MARK: - Object Methods
    429 
    430 /*!
    431  *	@brief
    432  *		Allocate the memory for the reference counted object.
    433  *
    434  *	@param size
    435  *		The size of the object to be allocated.
    436  *
    437  *	@result
    438  *		The memory allocated for the object, or <code>NULL</code> if the memory allocation fails.
    439  */
    440 ref_count_obj_t NULLABLE
    441 ref_count_obj_alloc(size_t size);
    442 
    443 /*!
    444  *	@brief
    445  *		Set the object's kind and do memory initialization. Under most of cases, memory initialization will not be performed. (zero initialization is already finished by
    446  *		<code>ref_count_obj_alloc()(</code>).
    447  *
    448  *	@param ref_count_object
    449  *		The newly allocated reference counted object.
    450  *
    451  *	@param new_kind
    452  *		The kind of this newly allocated reference counted object.
    453  *
    454  *	@discussion
    455  *		Any newly allocated object has to call this function to set its kind.
    456  */
    457 void
    458 ref_count_obj_init(ref_count_obj_any_t ref_count_object, ref_count_kind_t NONNULL new_kind);
    459 
    460 /*!
    461  *	@brief
    462  *		Retain a reference counted object by increasing the reference count by one.
    463  *
    464  *	@param ref_count_object
    465  *		The supported reference counted object contained in <code>ref_count_obj_any_t</code> union.
    466  *
    467  *	@result
    468  *		The retained reference counted object.
    469  */
    470 ref_count_obj_t NONNULL
    471 ref_count_obj_retain(ref_count_obj_any_t ref_count_object);
    472 
    473 /*!
    474  *	@brief
    475  *		Release a reference counted object by increasing the reference count by one. If the reference count becomes zero after releasing, the object will be
    476  *		finalized.
    477  *
    478  *	@param ref_count_object
    479  *		The supported reference counted object contained in <code>ref_count_obj_any_t</code> union.
    480  */
    481 void
    482 ref_count_obj_release(ref_count_obj_any_t ref_count_object);
    483 
    484 /*!
    485  *	@brief
    486  *		Compare two reference counted objects, based on the definition of the comparator of the object.
    487  *
    488  *	@param ref_count_object1
    489  *		The supported reference counted object contained in <code>ref_count_obj_any_t</code> union.
    490  *
    491  *	@param ref_count_object2
    492  *		The supported reference counted object contained in <code>ref_count_obj_any_t</code> union.
    493  *
    494  *	@param check_equality_only
    495  *		Indicate whether the caller only wants to know if the two objects are equal or not. The comparison will be faster when it is true.
    496  *
    497  *	@result
    498  *		<code>compare_result_less</code> if <code>ref_count_object1</code> is less than <code>ref_count_object2</code>.
    499  *		<code>compare_result_equal</code> if <code>ref_count_object1</code> is equal to <code>ref_count_object2</code>.
    500  *		<code>compare_result_greater</code> if <code>ref_count_object1</code> is greater than <code>ref_count_object2</code>.
    501  *		<code>compare_result_notequal</code> if two objects can be compared and they are not equal, but the specific order of the two objects cannot be determined.
    502  *		<code>compare_result_unknown</code> if two objects have different kind or no any comparator available to determine the comparison result, or any unexpected
    503  *			cases defined by the comparator.
    504  *
    505  *	@discussion
    506  *		If the kind of the two objects has no comparator defined, the comparator of the super kind will be used to determine their equality. Such process will
    507  *		continue until one available comparator is found or the root kind (NULL) is reached. If no comparator is available for the current kind, the result will be
    508  *		<code>compare_result_unknown</code>.
    509  */
    510 compare_result_t
    511 ref_count_obj_compare(ref_count_obj_any_t ref_count_object1, ref_count_obj_any_t ref_count_object2, bool check_equality_only);
    512 
    513 /*!
    514  *	@brief
    515  *		Sort the reference counted objects array by the ascending or descending order.
    516  *
    517  *	@param ref_count_objects
    518  *		The reference counted object array to be sorted.
    519  *
    520  *	@param count
    521  *		The number of objects in the array.
    522  *
    523  *	@param order
    524  *		The order of the sorted array, it can be
    525  *		<code>sort_order_ascending</code> for the ascending order.
    526  *		<code>sort_order_descending</code> for the descending order.
    527  *
    528  *	@discussion
    529  *		The object has to have a comparator that can determine the specific order of the two objects that have the same kind, in order to be sortable. If no
    530  *		comparator is available or the comparator can only determine the equality of the objects, the array will be returned untouched.
    531  */
    532 void
    533 ref_count_objs_sort(ref_count_objs_any_t ref_count_objects, size_t count, sort_order_t order);
    534 
    535 #endif // REF_COUNT_H
    536