id_manager: Use array of bool instead of list

Instead of storing the acquired context ids in a linked list, use an
array of booleans for the job. A boolean value of true in the array
designates an available context id.
This commit is contained in:
Reto Buerki 2012-08-09 12:47:58 +02:00 committed by Tobias Brunner
parent 49c513c1d9
commit 7aa573a50e
2 changed files with 42 additions and 41 deletions

View File

@ -20,6 +20,8 @@
#include <collections/linked_list.h>
#include <threading/rwlock.h>
#define TKM_LIMIT 100
ENUM_BEGIN(tkm_context_kind_names, TKM_CTX_NONCE, TKM_CTX_DH,
"NONCE_CONTEXT",
"DH_CONTEXT");
@ -38,14 +40,9 @@ struct private_tkm_id_manager_t {
tkm_id_manager_t public;
/**
* Next free context id values.
* Per-kind array of free context ids
*/
int nextids[TKM_CTX_MAX];
/**
* Per-kind list of acquired context ids
*/
linked_list_t *ctxids[TKM_CTX_MAX];
bool* ctxids[TKM_CTX_MAX];
/**
* rwlocks for context id lists
@ -69,8 +66,7 @@ static bool is_valid_kind(const tkm_context_kind_t kind)
METHOD(tkm_id_manager_t, acquire_id, int,
private_tkm_id_manager_t * const this, const tkm_context_kind_t kind)
{
int *current;
int id = 0;
int j, id = 0;
if (!is_valid_kind(kind))
{
@ -80,13 +76,15 @@ METHOD(tkm_id_manager_t, acquire_id, int,
}
this->locks[kind]->write_lock(this->locks[kind]);
id = this->nextids[kind];
current = malloc(sizeof(int));
*current = id;
this->ctxids[kind]->insert_last(this->ctxids[kind], current);
this->nextids[kind]++;
for (j = 0; j < TKM_LIMIT; j++)
{
if (this->ctxids[kind][j])
{
this->ctxids[kind][j] = false;
id = j + 1;
break;
}
}
this->locks[kind]->unlock(this->locks[kind]);
if (!id)
@ -102,9 +100,7 @@ METHOD(tkm_id_manager_t, release_id, bool,
private_tkm_id_manager_t * const this, const tkm_context_kind_t kind,
const int id)
{
enumerator_t *enumerator;
int *current;
bool found = FALSE;
const int idx = id - 1;
if (!is_valid_kind(kind))
{
@ -114,25 +110,9 @@ METHOD(tkm_id_manager_t, release_id, bool,
}
this->locks[kind]->write_lock(this->locks[kind]);
enumerator = this->ctxids[kind]->create_enumerator(this->ctxids[kind]);
while (enumerator->enumerate(enumerator, &current))
{
if (*current == id)
{
this->ctxids[kind]->remove_at(this->ctxids[kind], enumerator);
found = TRUE;
break;
}
}
enumerator->destroy(enumerator);
this->ctxids[kind][idx] = true;
this->locks[kind]->unlock(this->locks[kind]);
if (!found)
{
DBG3(DBG_LIB, "releasing non-existent %N context id %d, nothing to do",
tkm_context_kind_names, kind, id);
}
return TRUE;
}
@ -141,10 +121,9 @@ METHOD(tkm_id_manager_t, destroy, void,
private_tkm_id_manager_t *this)
{
int i;
for (i = 0; i < TKM_CTX_MAX; i++)
{
this->ctxids[i]->destroy(this->ctxids[i]);
free(this->ctxids[i]);
this->locks[i]->destroy(this->locks[i]);
}
free(this);
@ -156,7 +135,7 @@ METHOD(tkm_id_manager_t, destroy, void,
tkm_id_manager_t *tkm_id_manager_create()
{
private_tkm_id_manager_t *this;
int i;
int i, j;
INIT(this,
.public = {
@ -168,9 +147,13 @@ tkm_id_manager_t *tkm_id_manager_create()
for (i = 0; i < TKM_CTX_MAX; i++)
{
this->nextids[i] = 1;
this->ctxids[i] = linked_list_create();
this->ctxids[i] = malloc(TKM_LIMIT * sizeof(bool));
this->locks[i] = rwlock_create(RWLOCK_TYPE_DEFAULT);
for (j = 0; j < TKM_LIMIT; j++)
{
/* available id slots are in true state (is_available) */
this->ctxids[i][j] = true;
}
}
return &this->public;

View File

@ -66,6 +66,23 @@ START_TEST(test_acquire_id_invalid_kind)
}
END_TEST
START_TEST(test_acquire_id_same)
{
int id1 = 0, id2 = 0;
tkm_id_manager_t *idmgr = tkm_id_manager_create();
id1 = idmgr->acquire_id(idmgr, TKM_CTX_NONCE);
fail_unless(id1 > 0, "Unable to acquire first id");
/* Acquire another id, must be different than first */
id2 = idmgr->acquire_id(idmgr, TKM_CTX_NONCE);
fail_unless(id2 > 0, "Unable to acquire second id");
fail_unless(id1 != id2, "Same id received twice");
idmgr->destroy(idmgr);
}
END_TEST
START_TEST(test_release_id)
{
int i, id = 0;
@ -123,6 +140,7 @@ TCase *make_id_manager_tests(void)
tcase_add_test(tc, test_id_mgr_creation);
tcase_add_test(tc, test_acquire_id);
tcase_add_test(tc, test_acquire_id_invalid_kind);
tcase_add_test(tc, test_acquire_id_same);
tcase_add_test(tc, test_release_id);
tcase_add_test(tc, test_release_id_invalid_kind);
tcase_add_test(tc, test_release_id_nonexistent);