summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Drake <michael.drake@codethink.co.uk>2021-07-03 13:54:26 +0100
committerMichael Drake <michael.drake@codethink.co.uk>2021-07-03 13:54:26 +0100
commitc60dcdb27441b0e71072ad90ee14c67b73b84910 (patch)
tree5294d56a3294d893293ece0171ec69d36ae00279
parent6f9b1a501fa8b95ba0befc9f3eea815f2ba4035d (diff)
downloadlibdom-tlsa/refcheck.tar.gz
libdom-tlsa/refcheck.tar.bz2
WIP: Refcheck: Add dom node reference counting checking helper.tlsa/refcheck
-rw-r--r--include/dom/core/node.h17
-rw-r--r--src/core/node.c4
-rw-r--r--src/utils/Makefile3
-rw-r--r--src/utils/refcheck.c69
4 files changed, 88 insertions, 5 deletions
diff --git a/include/dom/core/node.h b/include/dom/core/node.h
index 90026a1..37fd2b8 100644
--- a/include/dom/core/node.h
+++ b/include/dom/core/node.h
@@ -73,12 +73,18 @@ typedef enum {
typedef struct dom_node_internal dom_node_internal;
+struct dom_refcheck;
+struct dom_refcheck *dom_refcheck(
+ struct dom_refcheck *rc,
+ uint32_t refcnt);
+
/**
* DOM node type
*/
typedef struct dom_node {
const void *vtable;
uint32_t refcnt;
+ struct dom_refcheck *rc;
} dom_node;
/* DOM node vtable */
@@ -177,9 +183,11 @@ typedef struct dom_node_vtable {
static inline dom_node *dom_node_ref(dom_node *node)
{
- if (node != NULL)
+ if (node != NULL) {
node->refcnt++;
-
+ node->rc = dom_refcheck(node->rc, node->refcnt);
+ }
+
return node;
}
@@ -195,10 +203,11 @@ static inline dom_exception dom_node_try_destroy(dom_node *node)
static inline void dom_node_unref(dom_node *node)
{
if (node != NULL) {
- if (--node->refcnt == 0)
+ node->refcnt--;
+ node->rc = dom_refcheck(node->rc, node->refcnt);
+ if (node->refcnt == 0)
dom_node_try_destroy(node);
}
-
}
#define dom_node_unref(n) dom_node_unref((dom_node *) (n))
diff --git a/src/core/node.c b/src/core/node.c
index 1218742..0e3f818 100644
--- a/src/core/node.c
+++ b/src/core/node.c
@@ -199,7 +199,9 @@ dom_exception _dom_node_initialise(dom_node_internal *node,
node->user_data = NULL;
+ node->base.rc = dom_refcheck(NULL, 0);
node->base.refcnt = 1;
+ node->base.rc = dom_refcheck(node->base.rc, node->base.refcnt);
list_init(&node->pending_list);
if (node->type != DOM_DOCUMENT_NODE) {
@@ -1904,7 +1906,9 @@ dom_exception _dom_node_copy_internal(dom_node_internal *old,
new->prefix = NULL;
new->user_data = NULL;
+ new->base.rc = dom_refcheck(NULL, 0);
new->base.refcnt = 1;
+ new->base.rc = dom_refcheck(new->base.rc, new->base.refcnt);
list_init(&new->pending_list);
diff --git a/src/utils/Makefile b/src/utils/Makefile
index f891b6e..027e3a5 100644
--- a/src/utils/Makefile
+++ b/src/utils/Makefile
@@ -1,4 +1,5 @@
# Sources
-DIR_SOURCES := namespace.c hashtable.c character_valid.c validate.c walk.c
+DIR_SOURCES := namespace.c hashtable.c character_valid.c validate.c walk.c \
+ refcheck.c
include $(NSBUILD)/Makefile.subdir
diff --git a/src/utils/refcheck.c b/src/utils/refcheck.c
new file mode 100644
index 0000000..fbba568
--- /dev/null
+++ b/src/utils/refcheck.c
@@ -0,0 +1,69 @@
+/*
+ * This file is part of libdom.
+ * Licensed under the MIT License,
+ * http://www.opensource.org/licenses/mit-license.php
+ * Copyright 2021 Michael Drake <tlsa@netsurf-browser.org>
+ */
+
+/** \file
+ * This is an API for walking a loaded DOM.
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+
+#include <dom/dom.h>
+
+struct dom_refcheck {
+ size_t len;
+ uintptr_t *array;
+};
+
+struct dom_refcheck *dom_refcheck(
+ struct dom_refcheck *rc,
+ uint32_t refcnt)
+{
+ if (rc == NULL) {
+ rc = calloc(1, sizeof(*rc));
+ if (rc == NULL) {
+ goto out;
+ }
+
+ if (refcnt == 0) {
+ goto out;
+ }
+ }
+
+ fprintf(stderr, "%p: refcnt: %u, len: %zu\n", rc, refcnt, rc->len);
+
+ if (refcnt == rc->len - 1) {
+ //rc->array[refcnt] ^= UINTPTR_MAX;
+ free((void *)rc->array[refcnt]);
+ rc->array[refcnt] = (uintptr_t)NULL;
+ rc->len = refcnt;
+
+ } else if (refcnt == rc->len + 1) {
+ uintptr_t *temp = realloc(rc->array, sizeof(*temp) * refcnt);
+ if (temp == NULL) {
+ goto out;
+ }
+ rc->array = temp;
+
+ rc->array[rc->len] = (uintptr_t)malloc(1);
+ //rc->array[rc->len] ^= UINTPTR_MAX;
+ rc->len = refcnt;
+ }
+
+ if (refcnt == 0) {
+ free(rc->array);
+ free(rc);
+ rc = NULL;
+ goto out;
+
+ } else {
+ }
+
+out:
+ return rc;
+}