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
2013-03-19 15:23:45 +01:00
committed by Tobias Brunner
parent 49c513c1d9
commit 7aa573a50e
2 changed files with 42 additions and 41 deletions
+24 -41
View File
@@ -20,6 +20,8 @@
#include <collections/linked_list.h> #include <collections/linked_list.h>
#include <threading/rwlock.h> #include <threading/rwlock.h>
#define TKM_LIMIT 100
ENUM_BEGIN(tkm_context_kind_names, TKM_CTX_NONCE, TKM_CTX_DH, ENUM_BEGIN(tkm_context_kind_names, TKM_CTX_NONCE, TKM_CTX_DH,
"NONCE_CONTEXT", "NONCE_CONTEXT",
"DH_CONTEXT"); "DH_CONTEXT");
@@ -38,14 +40,9 @@ struct private_tkm_id_manager_t {
tkm_id_manager_t public; tkm_id_manager_t public;
/** /**
* Next free context id values. * Per-kind array of free context ids
*/ */
int nextids[TKM_CTX_MAX]; bool* ctxids[TKM_CTX_MAX];
/**
* Per-kind list of acquired context ids
*/
linked_list_t *ctxids[TKM_CTX_MAX];
/** /**
* rwlocks for context id lists * 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, METHOD(tkm_id_manager_t, acquire_id, int,
private_tkm_id_manager_t * const this, const tkm_context_kind_t kind) private_tkm_id_manager_t * const this, const tkm_context_kind_t kind)
{ {
int *current; int j, id = 0;
int id = 0;
if (!is_valid_kind(kind)) 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]); this->locks[kind]->write_lock(this->locks[kind]);
for (j = 0; j < TKM_LIMIT; j++)
id = this->nextids[kind]; {
current = malloc(sizeof(int)); if (this->ctxids[kind][j])
*current = id; {
this->ctxids[kind]->insert_last(this->ctxids[kind], current); this->ctxids[kind][j] = false;
this->nextids[kind]++; id = j + 1;
break;
}
}
this->locks[kind]->unlock(this->locks[kind]); this->locks[kind]->unlock(this->locks[kind]);
if (!id) 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, private_tkm_id_manager_t * const this, const tkm_context_kind_t kind,
const int id) const int id)
{ {
enumerator_t *enumerator; const int idx = id - 1;
int *current;
bool found = FALSE;
if (!is_valid_kind(kind)) 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]); this->locks[kind]->write_lock(this->locks[kind]);
enumerator = this->ctxids[kind]->create_enumerator(this->ctxids[kind]); this->ctxids[kind][idx] = true;
while (enumerator->enumerate(enumerator, &current))
{
if (*current == id)
{
this->ctxids[kind]->remove_at(this->ctxids[kind], enumerator);
found = TRUE;
break;
}
}
enumerator->destroy(enumerator);
this->locks[kind]->unlock(this->locks[kind]); 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; return TRUE;
} }
@@ -141,10 +121,9 @@ METHOD(tkm_id_manager_t, destroy, void,
private_tkm_id_manager_t *this) private_tkm_id_manager_t *this)
{ {
int i; int i;
for (i = 0; i < TKM_CTX_MAX; 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]); this->locks[i]->destroy(this->locks[i]);
} }
free(this); free(this);
@@ -156,7 +135,7 @@ METHOD(tkm_id_manager_t, destroy, void,
tkm_id_manager_t *tkm_id_manager_create() tkm_id_manager_t *tkm_id_manager_create()
{ {
private_tkm_id_manager_t *this; private_tkm_id_manager_t *this;
int i; int i, j;
INIT(this, INIT(this,
.public = { .public = {
@@ -168,9 +147,13 @@ tkm_id_manager_t *tkm_id_manager_create()
for (i = 0; i < TKM_CTX_MAX; i++) for (i = 0; i < TKM_CTX_MAX; i++)
{ {
this->nextids[i] = 1; this->ctxids[i] = malloc(TKM_LIMIT * sizeof(bool));
this->ctxids[i] = linked_list_create();
this->locks[i] = rwlock_create(RWLOCK_TYPE_DEFAULT); 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; return &this->public;
+18
View File
@@ -66,6 +66,23 @@ START_TEST(test_acquire_id_invalid_kind)
} }
END_TEST 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) START_TEST(test_release_id)
{ {
int i, id = 0; 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_id_mgr_creation);
tcase_add_test(tc, test_acquire_id); tcase_add_test(tc, test_acquire_id);
tcase_add_test(tc, test_acquire_id_invalid_kind); 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);
tcase_add_test(tc, test_release_id_invalid_kind); tcase_add_test(tc, test_release_id_invalid_kind);
tcase_add_test(tc, test_release_id_nonexistent); tcase_add_test(tc, test_release_id_nonexistent);