ref count type define supporting malloc/free being specified

This commit is contained in:
Dan Cristoloveanu 2020-08-14 22:59:18 -07:00
Родитель e4fcca3d79
Коммит e388bf105a
5 изменённых файлов: 86 добавлений и 12 удалений

Просмотреть файл

@ -13,14 +13,25 @@ It wraps the structure that needs to be ref counted into another structure that
#define REFCOUNT_TYPE_CREATE_WITH_EXTRA_SIZE(type, size) MU_C2(REFCOUNT_SHORT_TYPE(type), _Create_With_Extra_Size)(size)
#define REFCOUNT_TYPE_DESTROY(type, var) MU_C2(REFCOUNT_SHORT_TYPE(type), _Destroy)(var)
#define DEFINE_REFCOUNT_TYPE(type) \
#define INC_REF(type, var) interlocked_increment(&((REFCOUNT_TYPE(type)*)((unsigned char*)var - offsetof(REFCOUNT_TYPE(type), counted)))->count)
#define DEC_REF(type, var) interlocked_decrement(&((REFCOUNT_TYPE(type)*)((unsigned char*)var - offsetof(REFCOUNT_TYPE(type), counted)))->count)
#define INIT_REF(type, var) interlocked_exchange(&((REFCOUNT_TYPE(type)*)((unsigned char*)var - offsetof(REFCOUNT_TYPE(type), counted)))->count, 1)
#define DEFINE_REFCOUNT_TYPE(type, malloc_func, free_func) \
...
```
### DEFINE_REFCOUNT_TYPE
```c
#define DEFINE_REFCOUNT_TYPE(type, malloc_func, free_func) \
...
```
**SRS_REFCOUNT_01_001: [** `DEFINE_REFCOUNT_TYPE` shall define the create/create_with_Extra_size/destroy functions for the type `type`. **]**
**SRS_REFCOUNT_01_010: [** Memory allocation/free shall be performed by using the functions `malloc_func` and `free_func`. **]**
### REFCOUNT_TYPE_CREATE
```c

Просмотреть файл

@ -55,10 +55,11 @@ MU_C2(REFCOUNT_, type)
/* Codes_SRS_REFCOUNT_01_005: [ REFCOUNT_TYPE_CREATE_WITH_EXTRA_SIZE shall allocate memory for the type that is ref counted (type) plus extra memory enough to hold size bytes. ]*/
/* Codes_SRS_REFCOUNT_01_006: [ On success it shall return a non-NULL handle to the allocated ref counted type type. ]*/
/* Codes_SRS_REFCOUNT_01_007: [ If any error occurs, REFCOUNT_TYPE_CREATE_WITH_EXTRA_SIZE shall return NULL. ]*/
#define DEFINE_CREATE_WITH_EXTRA_SIZE(type) \
#define DEFINE_CREATE_WITH_EXTRA_SIZE(type, malloc_func) \
static type* REFCOUNT_TYPE_DECLARE_CREATE_WITH_EXTRA_SIZE(type)(size_t size) \
{ \
REFCOUNT_TYPE(type)* ref_counted = (REFCOUNT_TYPE(type)*)malloc(sizeof(REFCOUNT_TYPE(type)) + size); \
/* Codes_SRS_REFCOUNT_01_010: [ Memory allocation/free shall be performed by using the functions malloc_func and free_func. ]*/ \
REFCOUNT_TYPE(type)* ref_counted = (REFCOUNT_TYPE(type)*)malloc_func(sizeof(REFCOUNT_TYPE(type)) + size); \
type* result; \
if (ref_counted == NULL) \
{ \
@ -75,7 +76,7 @@ static type* REFCOUNT_TYPE_DECLARE_CREATE_WITH_EXTRA_SIZE(type)(size_t size) \
/* Codes_SRS_REFCOUNT_01_002: [ REFCOUNT_TYPE_CREATE shall allocate memory for the type that is ref counted. ]*/
/* Codes_SRS_REFCOUNT_01_003: [ On success it shall return a non-NULL handle to the allocated ref counted type type. ]*/
/* Codes_SRS_REFCOUNT_01_004: [ If any error occurs, REFCOUNT_TYPE_CREATE shall return NULL. ]*/
#define DEFINE_CREATE(type) \
#define DEFINE_CREATE(type, malloc_func) \
static type* REFCOUNT_TYPE_DECLARE_CREATE(type) (void) \
{ \
return REFCOUNT_TYPE_DECLARE_CREATE_WITH_EXTRA_SIZE(type)(0); \
@ -83,23 +84,24 @@ static type* REFCOUNT_TYPE_DECLARE_CREATE(type) (void) \
/* Codes_SRS_REFCOUNT_01_008: [ REFCOUNT_TYPE_DESTROY shall free the memory allocated by REFCOUNT_TYPE_CREATE or REFCOUNT_TYPE_CREATE_WITH_EXTRA_SIZE. ]*/
/* Codes_SRS_REFCOUNT_01_009: [ If counted_type is NULL, REFCOUNT_TYPE_DESTROY shall return. ]*/
#define DEFINE_DESTROY(type) \
#define DEFINE_DESTROY(type, free_func) \
static void REFCOUNT_TYPE_DECLARE_DESTROY(type)(type* counted_type) \
{ \
void* ref_counted = (void*)((unsigned char*)counted_type - offsetof(REFCOUNT_TYPE(type), counted)); \
free(ref_counted); \
/* Codes_SRS_REFCOUNT_01_010: [ Memory allocation/free shall be performed by using the functions malloc_func and free_func. ]*/ \
free_func(ref_counted); \
}
/* Codes_SRS_REFCOUNT_01_001: [ DEFINE_REFCOUNT_TYPE shall define the create/create_with_Extra_size/destroy functions for the type type. ]*/
#define DEFINE_REFCOUNT_TYPE(type) \
#define DEFINE_REFCOUNT_TYPE(type, malloc_func, free_func) \
REFCOUNT_TYPE(type) \
{ \
volatile_atomic int32_t count; \
type counted; \
}; \
DEFINE_CREATE_WITH_EXTRA_SIZE(type) \
DEFINE_CREATE(type) \
DEFINE_DESTROY(type) \
DEFINE_CREATE_WITH_EXTRA_SIZE(type, malloc_func) \
DEFINE_CREATE(type, malloc_func) \
DEFINE_DESTROY(type, free_func) \
/*assuming that CONSTBUFFER_ARRAY_HANDLE is a type introduced with DEFINE_REFCOUNT_TYPE(CONSTBUFFER_ARRAY_HANDLE_DATA);
and "checkpointContent" is a variable of type CONSTBUFFER_ARRAY_HANDLE

Просмотреть файл

@ -32,6 +32,7 @@ void my_free(void* ptr)
#include "azure_c_pal/interlocked.h"
#include "azure_c_pal/gballoc_hl.h"
#include "azure_c_pal/gballoc_hl_redirect.h"
#include "azure_c_pal/refcount.h"
#undef ENABLE_MOCKS
#include "real_gballoc_hl.h"
@ -46,6 +47,19 @@ static void on_umock_c_error(UMOCK_C_ERROR_CODE error_code)
ASSERT_FAIL("umock_c reported error :%" PRI_MU_ENUM "", MU_ENUM_VALUE(UMOCK_C_ERROR_CODE, error_code));
}
typedef struct TEST_STRUCT_TAG
{
int dummy;
} TEST_STRUCT;
MOCK_FUNCTION_WITH_CODE(, void*, test_malloc, size_t, size)
MOCK_FUNCTION_END(my_malloc(size))
MOCK_FUNCTION_WITH_CODE(, void, test_free, void*, ptr)
my_free(ptr);
MOCK_FUNCTION_END()
DEFINE_REFCOUNT_TYPE(TEST_STRUCT, test_malloc, test_free);
BEGIN_TEST_SUITE(refcount_unittests)
TEST_SUITE_INITIALIZE(TestClassInitialize)
@ -240,4 +254,50 @@ BEGIN_TEST_SUITE(refcount_unittests)
ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls());
}
/* Tests_SRS_REFCOUNT_01_010: [ Memory allocation/free shall be performed by using the functions malloc_func and free_func. ]*/ \
TEST_FUNCTION(the_specified_malloc_function_from_the_define_is_used)
{
///arrange
STRICT_EXPECTED_CALL(test_malloc(IGNORED_ARG));
STRICT_EXPECTED_CALL(interlocked_exchange(IGNORED_ARG, 1));
///act
TEST_STRUCT* result = REFCOUNT_TYPE_CREATE(TEST_STRUCT);
///assert
ASSERT_IS_NOT_NULL(result);
ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls());
}
/* Tests_SRS_REFCOUNT_01_010: [ Memory allocation/free shall be performed by using the functions malloc_func and free_func. ]*/ \
TEST_FUNCTION(the_specified_malloc_function_from_the_define_is_used_by_create_with_extra_size)
{
///arrange
STRICT_EXPECTED_CALL(test_malloc(IGNORED_ARG));
STRICT_EXPECTED_CALL(interlocked_exchange(IGNORED_ARG, 1));
///act
TEST_STRUCT* result = REFCOUNT_TYPE_CREATE_WITH_EXTRA_SIZE(TEST_STRUCT, 1);
///assert
ASSERT_IS_NOT_NULL(result);
ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls());
}
/* Tests_SRS_REFCOUNT_01_010: [ Memory allocation/free shall be performed by using the functions malloc_func and free_func. ]*/ \
TEST_FUNCTION(the_specified_free_function_from_the_define_is_used)
{
///arrange
TEST_STRUCT* result = REFCOUNT_TYPE_CREATE(TEST_STRUCT);
umock_c_reset_all_calls();
STRICT_EXPECTED_CALL(test_free(IGNORED_ARG));
///act
REFCOUNT_TYPE_DESTROY(TEST_STRUCT, result);
///assert
ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls());
}
END_TEST_SUITE(refcount_unittests)

Просмотреть файл

@ -14,7 +14,8 @@ typedef struct pos_TAG
} pos;
/* Tests_SRS_REFCOUNT_01_001: [ DEFINE_REFCOUNT_TYPE shall define the create/create_with_Extra_size/destroy functions for the type type. ]*/
DEFINE_REFCOUNT_TYPE(pos);
/* Tests_SRS_REFCOUNT_01_010: [ Memory allocation/free shall be performed by using the functions `malloc_func` and `free_func`. ]*/ \
DEFINE_REFCOUNT_TYPE(pos, malloc, free);
POS_HANDLE Pos_Create(int x)
{

Просмотреть файл

@ -14,7 +14,7 @@ typedef struct EXECUTION_ENGINE_TAG
PTP_POOL ptp_pool;
}EXECUTION_ENGINE;
DEFINE_REFCOUNT_TYPE(EXECUTION_ENGINE);
DEFINE_REFCOUNT_TYPE(EXECUTION_ENGINE, malloc, free);
EXECUTION_ENGINE_HANDLE execution_engine_create(void* execution_engine_parameters)
{