astobj2: Avoid using temporary objects + ao2_find() with OBJ_POINTER.

There is a fairly common pattern making its way through the code base where we
put a temporary object on the stack so we can call ao2_find() with OBJ_POINTER.
The purpose is so that it can be passed into the object hash function.
However, this really seems like a hack and potentially error prone.  This patch
is a first stab at approach to avoid having to do that.

It adds a new flag, OBJ_KEY, which can be used instead of OBJ_POINTER in these
situations.  Then, the hash function can know whether it was given an object or
some custom data to hash.

The patch also changes some uses of ao2_find() for iax2_user and iax2_peer
objects to reflect how OBJ_KEY would be used.

So long, and thanks for all the fish.

Review: https://reviewboard.asterisk.org/r/1184/


git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@330273 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
Russell Bryant
2011-07-29 19:34:36 +00:00
parent d2ed4ed5f7
commit 6a15e95a32
4 changed files with 76 additions and 54 deletions

View File

@@ -38,7 +38,6 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/astobj2.h"
struct test_obj {
char c[20];
int i;
int *destructor_count;
};
@@ -75,20 +74,35 @@ static int multiple_cb(void *obj, void *arg, int flag)
static int test_cmp_cb(void *obj, void *arg, int flags)
{
struct test_obj *cmp_obj = (struct test_obj *) obj;
struct test_obj *test_obj = (struct test_obj *) arg;
if (!arg) {
return 0;
}
return (cmp_obj->i == test_obj->i) ? CMP_MATCH | CMP_STOP : 0;
if (flags & OBJ_KEY) {
int *i = (int *) arg;
return (cmp_obj->i == *i) ? CMP_MATCH | CMP_STOP : 0;
} else {
struct test_obj *test_obj = (struct test_obj *) arg;
return (cmp_obj->i == test_obj->i) ? CMP_MATCH | CMP_STOP : 0;
}
}
static int test_hash_cb(const void *obj, const int flags)
{
struct test_obj *test_obj = (struct test_obj *) obj;
if (!test_obj || ast_strlen_zero(test_obj->c)) {
if (!obj) {
return 0;
}
return ast_str_hash(test_obj->c);
if (flags & OBJ_KEY) {
const int *i = obj;
return *i;
} else {
const struct test_obj *test_obj = obj;
return test_obj->i;
}
}
static int astobj2_test_helper(int use_hash, int use_cmp, unsigned int lim, struct ast_test *test)
@@ -128,7 +142,6 @@ static int astobj2_test_helper(int use_hash, int use_cmp, unsigned int lim, stru
res = AST_TEST_FAIL;
goto cleanup;
}
snprintf(obj->c, sizeof(obj->c), "zombie #%d", num);
obj->destructor_count = &destructor_count;
obj->i = num;
ao2_link(c1, obj);
@@ -163,7 +176,6 @@ static int astobj2_test_helper(int use_hash, int use_cmp, unsigned int lim, stru
num = 75;
for (; num; num--) {
int i = (ast_random() % ((lim / 2)) + 1); /* find a random object */
snprintf(tmp_obj.c, sizeof(tmp_obj.c), "zombie #%d", i);
tmp_obj.i = i;
if (!(obj = ao2_find(c1, &tmp_obj, OBJ_POINTER))) {
res = AST_TEST_FAIL;
@@ -178,6 +190,23 @@ static int astobj2_test_helper(int use_hash, int use_cmp, unsigned int lim, stru
}
}
/* Testing ao2_find with OBJ_KEY */
num = 75;
for (; num; num--) {
int i = (ast_random() % ((lim / 2)) + 1); /* find a random object */
if (!(obj = ao2_find(c1, &i, OBJ_KEY))) {
res = AST_TEST_FAIL;
ast_test_status_update(test, "COULD NOT FIND:%d, ao2_find() with OBJ_KEY flag failed.\n", i);
} else {
/* a correct match will only take place when the custom cmp function is used */
if (use_cmp && obj->i != i) {
ast_test_status_update(test, "object %d does not match object %d\n", obj->i, tmp_obj.i);
res = AST_TEST_FAIL;
}
ao2_t_ref(obj, -1, "test");
}
}
/* Testing ao2_find with OBJ_POINTER | OBJ_UNLINK | OBJ_CONTINUE.
* In this test items are unlinked from c1 and placed in c2. Then
* unlinked from c2 and placed back into c1.
@@ -374,7 +403,7 @@ AST_TEST_DEFINE(astobj2_test_2)
int num;
static const int NUM_OBJS = 5;
int destructor_count = NUM_OBJS;
struct test_obj tmp_obj = { "", };
struct test_obj tmp_obj = { 0, };
switch (cmd) {
case TEST_INIT: