summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Mark Bell <jmb@netsurf-browser.org>2009-07-28 00:21:12 +0000
committerJohn Mark Bell <jmb@netsurf-browser.org>2009-07-28 00:21:12 +0000
commit3e5284a0da373cc2e83a934af14c90f46cc4f547 (patch)
tree2a4006dd86e586cf45438caf010ec9babf9b98bb
parentd398997c9328e1a32bb37084f8c45fee6a2557ee (diff)
downloadlibwapcaplet-3e5284a0da373cc2e83a934af14c90f46cc4f547.tar.gz
Keep a record of the amount of memory consumed by a lwc_context.
svn path=/trunk/libwapcaplet/; revision=8834
-rw-r--r--include/libwapcaplet/libwapcaplet.h5
-rw-r--r--src/libwapcaplet.c26
-rw-r--r--test/basictests.c116
3 files changed, 144 insertions, 3 deletions
diff --git a/include/libwapcaplet/libwapcaplet.h b/include/libwapcaplet/libwapcaplet.h
index 420f8c3..3b0899d 100644
--- a/include/libwapcaplet/libwapcaplet.h
+++ b/include/libwapcaplet/libwapcaplet.h
@@ -140,4 +140,9 @@ extern size_t lwc_string_length(lwc_string *str);
*/
extern uint32_t lwc_string_hash_value(lwc_string *str);
+/**
+ * Retrieve the size, in bytes, of internment context \a ctx.
+ */
+extern size_t lwc_context_size(lwc_context *ctx);
+
#endif /* libwapcaplet_h_ */
diff --git a/src/libwapcaplet.c b/src/libwapcaplet.c
index 87704bd..4996c6f 100644
--- a/src/libwapcaplet.c
+++ b/src/libwapcaplet.c
@@ -53,6 +53,7 @@ struct lwc_context_s {
lwc_string * buckets[NR_BUCKETS];
lwc_refcounter refcnt;
bool refweak;
+ size_t size;
};
lwc_error
@@ -72,6 +73,7 @@ lwc_create_context(lwc_allocator_fn alloc, void *pw,
(*ret)->alloc_pw = pw;
(*ret)->refcnt = 1;
(*ret)->refweak = true;
+ (*ret)->size = sizeof(lwc_context);
return lwc_error_ok;
}
@@ -130,6 +132,7 @@ __lwc_context_intern(lwc_context *ctx,
lwc_hash h;
lwc_hash bucket;
lwc_string *str;
+ size_t required_size;
assert(ctx);
assert((s != NULL) || (slen == 0));
@@ -151,7 +154,9 @@ __lwc_context_intern(lwc_context *ctx,
}
/* Add one for the additional NUL. */
- *ret = str = LWC_ALLOC(sizeof(lwc_string) + slen + 1);
+ required_size = sizeof(lwc_string) + slen + 1;
+
+ *ret = str = LWC_ALLOC(required_size);
if (str == NULL)
return lwc_error_oom;
@@ -161,7 +166,10 @@ __lwc_context_intern(lwc_context *ctx,
if (str->next != NULL)
str->next->prevptr = &(str->next);
ctx->buckets[bucket] = str;
-
+
+ /* Keep context size in sync */
+ ctx->size += required_size;
+
str->len = slen;
str->hash = h;
str->refcnt = 1;
@@ -235,7 +243,10 @@ lwc_context_string_unref(lwc_context *ctx, lwc_string *str)
if (str->insensitive != NULL && str->refcnt == 0)
lwc_context_string_unref(ctx, str->insensitive);
-
+
+ /* Reduce context size by appropriate amount (+1 for trailing NUL) */
+ ctx->size -= sizeof(lwc_string) + str->len + 1;
+
#ifndef NDEBUG
memset(str, 0xA5, sizeof(*str) + str->len);
#endif
@@ -353,3 +364,12 @@ lwc_string_hash_value(lwc_string *str)
return str->hash;
}
+
+size_t
+lwc_context_size(lwc_context *ctx)
+{
+ assert(ctx);
+
+ return ctx->size;
+}
+
diff --git a/test/basictests.c b/test/basictests.c
index 290a56c..cedb0c3 100644
--- a/test/basictests.c
+++ b/test/basictests.c
@@ -180,6 +180,12 @@ START_TEST (test_lwc_string_hash_value_aborts)
}
END_TEST
+START_TEST (test_lwc_context_size_aborts)
+{
+ lwc_context_size(NULL);
+}
+END_TEST
+
#endif
START_TEST (test_lwc_context_creation_ok)
@@ -276,6 +282,105 @@ START_TEST (test_lwc_context_intern_twice_same_ok)
}
END_TEST
+START_TEST (test_lwc_context_size_non_zero)
+{
+ fail_unless(lwc_context_size(shared_ctx) > 0,
+ "Size of empty context is zero");
+}
+END_TEST
+
+START_TEST (test_lwc_context_size_updated_on_string_intern)
+{
+ size_t empty_size = lwc_context_size(shared_ctx);
+ lwc_string *str;
+
+ fail_unless(empty_size > 0,
+ "Size of empty context is zero");
+
+ fail_unless(lwc_context_intern(shared_ctx, "one", 3, &str) == lwc_error_ok,
+ "Unable to intern a simple string");
+
+ fail_unless(lwc_context_size(shared_ctx) > empty_size,
+ "Post-intern context size is same or smaller than empty size");
+}
+END_TEST
+
+START_TEST (test_lwc_context_size_updated_on_string_unref)
+{
+ size_t empty_size = lwc_context_size(shared_ctx);
+ lwc_string *str;
+
+ fail_unless(empty_size > 0,
+ "Size of empty context is zero");
+
+ fail_unless(lwc_context_intern(shared_ctx, "one", 3, &str) == lwc_error_ok,
+ "Unable to intern a simple string");
+
+ fail_unless(lwc_context_size(shared_ctx) > empty_size,
+ "Post-intern context size is same or smaller than empty size");
+
+ lwc_context_string_unref(shared_ctx, str);
+
+ fail_unless(lwc_context_size(shared_ctx) == empty_size,
+ "Post-unref context size is not the same as empty size");
+}
+END_TEST
+
+START_TEST (test_lwc_context_size_updated_on_substring_intern)
+{
+ size_t empty_size = lwc_context_size(shared_ctx);
+ size_t post_intern_size = 0;
+ lwc_string *str, *str2;
+
+ fail_unless(empty_size > 0,
+ "Size of empty context is zero");
+
+ fail_unless(lwc_context_intern(shared_ctx, "one", 3, &str) == lwc_error_ok,
+ "Unable to intern a simple string");
+
+ post_intern_size = lwc_context_size(shared_ctx);
+
+ fail_unless(post_intern_size > empty_size,
+ "Post-intern context size is same or smaller than empty size");
+
+ fail_unless(lwc_context_intern_substring(shared_ctx, str, 0, 1, &str2) == lwc_error_ok,
+ "Failed to intern substring");
+
+ fail_unless(lwc_context_size(shared_ctx) > post_intern_size,
+ "Post-substring-intern context size is same or smaller than pre-substring-intern size");
+}
+END_TEST
+
+START_TEST (test_lwc_context_size_updated_on_substring_unref)
+{
+ size_t empty_size = lwc_context_size(shared_ctx);
+ size_t post_intern_size = 0;
+ lwc_string *str, *str2;
+
+ fail_unless(empty_size > 0,
+ "Size of empty context is zero");
+
+ fail_unless(lwc_context_intern(shared_ctx, "one", 3, &str) == lwc_error_ok,
+ "Unable to intern a simple string");
+
+ post_intern_size = lwc_context_size(shared_ctx);
+
+ fail_unless(post_intern_size > empty_size,
+ "Post-intern context size is same or smaller than empty size");
+
+ fail_unless(lwc_context_intern_substring(shared_ctx, str, 0, 1, &str2) == lwc_error_ok,
+ "Failed to intern substring");
+
+ fail_unless(lwc_context_size(shared_ctx) > post_intern_size,
+ "Post-substring-intern context size is same or smaller than pre-substring-intern size");
+
+ lwc_context_string_unref(shared_ctx, str2);
+
+ fail_unless(lwc_context_size(shared_ctx) == post_intern_size,
+ "Post-substring-unref size is not the same as pre-substring-intern size");
+}
+END_TEST
+
/**** The next set of tests need a fixture set with some strings ****/
static lwc_string *intern_one = NULL, *intern_two = NULL, *intern_three = NULL;
@@ -487,6 +592,9 @@ lwc_basic_suite(SRunner *sr)
tcase_add_test_raise_signal(tc_basic,
test_lwc_string_hash_value_aborts,
SIGABRT);
+ tcase_add_test_raise_signal(tc_basic,
+ test_lwc_context_size_aborts,
+ SIGABRT);
#endif
tcase_add_test(tc_basic, test_lwc_context_creation_ok);
@@ -501,6 +609,14 @@ lwc_basic_suite(SRunner *sr)
tcase_add_test(tc_basic, test_lwc_context_intern_ok);
tcase_add_test(tc_basic, test_lwc_context_intern_twice_ok);
tcase_add_test(tc_basic, test_lwc_context_intern_twice_same_ok);
+ tcase_add_test(tc_basic, test_lwc_context_size_non_zero);
+ tcase_add_test(tc_basic,
+ test_lwc_context_size_updated_on_string_intern);
+ tcase_add_test(tc_basic, test_lwc_context_size_updated_on_string_unref);
+ tcase_add_test(tc_basic,
+ test_lwc_context_size_updated_on_substring_intern);
+ tcase_add_test(tc_basic,
+ test_lwc_context_size_updated_on_substring_unref);
suite_add_tcase(s, tc_basic);
tc_basic = tcase_create("Ops with a filled context");