Add generic reference counting implementation ##util (#16604)

* Unit test for the r-ref api
This commit is contained in:
pancake 2020-04-17 05:56:28 +02:00 committed by GitHub
parent f549eb2a28
commit 0baf99d81d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 51 additions and 0 deletions

View File

@ -5,6 +5,7 @@
#include "r_util/r_str_util.h"
#include <r_userconf.h>
#include <stddef.h>
#include <assert.h>
// TODO: fix this to make it crosscompile-friendly: R_SYS_OSTYPE ?
/* operating system */
@ -654,4 +655,17 @@ static inline void r_run_call10(void *fcn, void *arg1, void *arg2, void *arg3, v
# endif
#endif
// reference counter
typedef int RRef;
#define R_REF_NAME refcount
#define r_ref(x) x->R_REF_NAME++;
#define r_ref_init(x) x->R_REF_NAME = 1
#define r_unref(x,f) { assert (x->R_REF_NAME> 0); if (!--(x->R_REF_NAME)) { f(x); } }
#define R_REF_TYPE RRef refcount;
#define R_REF_FUNCTIONS(s, n) \
static inline void n##_ref(s *x) { x->R_REF_NAME++; } \
static inline void n##_unref(s *x) { r_unref (x, n##_free); }
#endif // R2_TYPES_H

View File

@ -126,10 +126,47 @@ bool test_initial_underscore(void) {
mu_end;
}
/* references */
typedef struct {
const char *name;
R_REF_TYPE;
} TypeTest;
static TypeTest *r_type_test_new(const char *name) {
TypeTest *tt = R_NEW0 (TypeTest);
if (tt) {
r_ref_init (tt);
tt->name = name;
}
return tt;
}
static void r_type_test_free(TypeTest *tt) {
tt->name = "";
}
R_REF_FUNCTIONS(TypeTest, r_type_test);
bool test_references(void) {
TypeTest *tt = r_type_test_new ("foo");
mu_assert_eq (tt->refcount, 1, "reference count issue");
r_type_test_ref (tt);
mu_assert_eq (tt->refcount, 2, "reference count issue");
r_type_test_unref (tt);
mu_assert_streq (tt->name, "foo", "typetest name should be foo");
mu_assert_eq (tt->refcount, 1, "reference count issue");
r_type_test_unref (tt); // tt becomes invalid
mu_assert_eq (tt->refcount, 0, "reference count issue");
mu_assert_streq (tt->name, "", "typetest name should be foo");
free (tt);
mu_end;
}
int all_tests() {
mu_run_test (test_ignore_prefixes);
mu_run_test (test_remove_r2_prefixes);
mu_run_test (test_dll_names);
mu_run_test (test_references);
mu_run_test (test_autonames);
mu_run_test (test_initial_underscore);
return tests_passed != tests_run;