atomics: Add a ref_get() variant returning non-zero on overflows
This is useful for users using ref_get() for unique identifier allocation, but the zero value has special meaning.
This commit is contained in:
@@ -256,6 +256,26 @@ START_TEST(test_round)
|
|||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
* ref_get/put
|
||||||
|
*/
|
||||||
|
|
||||||
|
START_TEST(test_refs)
|
||||||
|
{
|
||||||
|
refcount_t r = 0xfffffffe;
|
||||||
|
|
||||||
|
ck_assert_int_eq(ref_cur(&r), 0xfffffffe);
|
||||||
|
ck_assert_int_eq(ref_get(&r), 0xffffffff);
|
||||||
|
ck_assert_int_eq(ref_get_nonzero(&r), 1);
|
||||||
|
ck_assert_int_eq(ref_get_nonzero(&r), 2);
|
||||||
|
ck_assert_int_eq(ref_cur(&r), 2);
|
||||||
|
ck_assert(!ref_put(&r));
|
||||||
|
ck_assert_int_eq(ref_cur(&r), 1);
|
||||||
|
ck_assert(ref_put(&r));
|
||||||
|
ck_assert_int_eq(ref_cur(&r), 0);
|
||||||
|
}
|
||||||
|
END_TEST
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
* streq
|
* streq
|
||||||
*/
|
*/
|
||||||
@@ -1272,6 +1292,10 @@ Suite *utils_suite_create()
|
|||||||
tcase_add_test(tc, test_round);
|
tcase_add_test(tc, test_round);
|
||||||
suite_add_tcase(s, tc);
|
suite_add_tcase(s, tc);
|
||||||
|
|
||||||
|
tc = tcase_create("refcount");
|
||||||
|
tcase_add_test(tc, test_refs);
|
||||||
|
suite_add_tcase(s, tc);
|
||||||
|
|
||||||
tc = tcase_create("string helper");
|
tc = tcase_create("string helper");
|
||||||
tcase_add_loop_test(tc, test_streq, 0, countof(streq_data));
|
tcase_add_loop_test(tc, test_streq, 0, countof(streq_data));
|
||||||
tcase_add_loop_test(tc, test_strneq, 0, countof(strneq_data));
|
tcase_add_loop_test(tc, test_strneq, 0, countof(strneq_data));
|
||||||
|
|||||||
@@ -124,6 +124,33 @@ bool cas_ptr(void **ptr, void *oldval, void *newval);
|
|||||||
|
|
||||||
#endif /* HAVE_GCC_ATOMIC_OPERATIONS */
|
#endif /* HAVE_GCC_ATOMIC_OPERATIONS */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a new reference, but skip zero on overflow.
|
||||||
|
*
|
||||||
|
* If a reference counter is used to allocate unique identifiers, the
|
||||||
|
* refcount value may overflow if it is never decremented. The 0 identifier
|
||||||
|
* may have special semantics, hence returning can be problematic for some
|
||||||
|
* users.
|
||||||
|
*
|
||||||
|
* This call does an additional ref_get() if ref_get() overflows and returns
|
||||||
|
* zero. This ensures that zero is never returned, in the assumption that it
|
||||||
|
* has special meaning.
|
||||||
|
*
|
||||||
|
* @param ref pointer to ref counter
|
||||||
|
* @return new value of ref
|
||||||
|
*/
|
||||||
|
static inline refcount_t ref_get_nonzero(refcount_t *ref)
|
||||||
|
{
|
||||||
|
refcount_t v;
|
||||||
|
|
||||||
|
v = ref_get(ref);
|
||||||
|
if (v == 0)
|
||||||
|
{
|
||||||
|
v = ref_get(ref);
|
||||||
|
}
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialize atomics utility functions
|
* Initialize atomics utility functions
|
||||||
*/
|
*/
|
||||||
|
|||||||
Reference in New Issue
Block a user