From 049a7b8be2a42f4a115de63eb1a202dd667a6723 Mon Sep 17 00:00:00 2001 From: Bert Belder Date: Mon, 25 Sep 2017 17:53:11 +0200 Subject: [PATCH] reflock-tree: add mechanism for pointer-safe tree lookups --- src/reflock-tree.c | 74 ++++++++++++++++++++++++++++++++++++++++++++++ src/reflock-tree.h | 37 +++++++++++++++++++++++ 2 files changed, 111 insertions(+) create mode 100644 src/reflock-tree.c create mode 100644 src/reflock-tree.h diff --git a/src/reflock-tree.c b/src/reflock-tree.c new file mode 100644 index 0000000..05224f2 --- /dev/null +++ b/src/reflock-tree.c @@ -0,0 +1,74 @@ +#include + +#include "reflock-tree.h" +#include "reflock.h" +#include "tree.h" +#include "util.h" +#include "win.h" + +void reflock_tree_init(reflock_tree_t* rlt) { + tree_init(&rlt->tree); + InitializeSRWLock(&rlt->lock); +} + +void reflock_tree_node_init(reflock_tree_node_t* node) { + tree_node_init(&node->tree_node); + reflock_init(&node->reflock); +} + +int reflock_tree_add(reflock_tree_t* rlt, + reflock_tree_node_t* node, + uintptr_t key) { + int r; + + AcquireSRWLockExclusive(&rlt->lock); + r = tree_add(&rlt->tree, &node->tree_node, key); + ReleaseSRWLockExclusive(&rlt->lock); + + return r; +} + +reflock_tree_node_t* reflock_tree_del_and_ref(reflock_tree_t* rlt, + uintptr_t key) { + tree_node_t* tree_node; + reflock_tree_node_t* rlt_node; + + AcquireSRWLockExclusive(&rlt->lock); + + tree_node = tree_find(&rlt->tree, (uintptr_t) key); + rlt_node = safe_container_of(tree_node, reflock_tree_node_t, tree_node); + + if (rlt_node != NULL) { + tree_del(&rlt->tree, tree_node); + reflock_ref(&rlt_node->reflock); + } + + ReleaseSRWLockExclusive(&rlt->lock); + + return rlt_node; +} + +reflock_tree_node_t* reflock_tree_find_and_ref(reflock_tree_t* rlt, + uintptr_t key) { + tree_node_t* tree_node; + reflock_tree_node_t* rlt_node; + + AcquireSRWLockShared(&rlt->lock); + + tree_node = tree_find(&rlt->tree, (uintptr_t) key); + rlt_node = safe_container_of(tree_node, reflock_tree_node_t, tree_node); + if (rlt_node != NULL) + reflock_ref(&rlt_node->reflock); + + ReleaseSRWLockShared(&rlt->lock); + + return rlt_node; +} + +void reflock_tree_node_unref(reflock_tree_node_t* node) { + reflock_unref(&node->reflock); +} + +void reflock_tree_node_unref_and_destroy(reflock_tree_node_t* node) { + reflock_unref_and_destroy(&node->reflock); +} diff --git a/src/reflock-tree.h b/src/reflock-tree.h new file mode 100644 index 0000000..64df2a3 --- /dev/null +++ b/src/reflock-tree.h @@ -0,0 +1,37 @@ +#ifndef REFLOCK_TREE_H_ +#define REFLOCK_TREE_H_ + +#include + +#include "internal.h" +#include "reflock.h" +#include "tree.h" +#include "win.h" + +typedef struct reflock_tree { + tree_t tree; + SRWLOCK lock; +} reflock_tree_t; + +typedef struct reflock_tree_node { + tree_node_t tree_node; + reflock_t reflock; +} reflock_tree_node_t; + +EPOLL_INTERNAL void reflock_tree_init(reflock_tree_t* rtl); +EPOLL_INTERNAL void reflock_tree_node_init(reflock_tree_node_t* node); + +EPOLL_INTERNAL int reflock_tree_add(reflock_tree_t* rlt, + reflock_tree_node_t* node, + uintptr_t key); + +EPOLL_INTERNAL reflock_tree_node_t* reflock_tree_del_and_ref( + reflock_tree_t* rlt, uintptr_t key); +EPOLL_INTERNAL reflock_tree_node_t* reflock_tree_find_and_ref( + reflock_tree_t* rlt, uintptr_t key); + +EPOLL_INTERNAL void reflock_tree_node_unref(reflock_tree_node_t* node); +EPOLL_INTERNAL void reflock_tree_node_unref_and_destroy( + reflock_tree_node_t* node); + +#endif /* REFLOCK_TREE_H_ */