summaryrefslogtreecommitdiffstats
path: root/server/util
diff options
context:
space:
mode:
authorMartin Nagy <mnagy@redhat.com>2009-10-06 01:34:55 +0200
committerSimo Sorce <ssorce@redhat.com>2009-11-06 18:06:05 -0500
commitc391633a8cc03f0fc3be0b7c424b28acf94bc878 (patch)
treee06df7285138bdf7134c4750dfe7b3d3c547312d /server/util
parent5f91071ac89de679e9f36e788d7bef757ea0e4bb (diff)
downloadsssd-c391633a8cc03f0fc3be0b7c424b28acf94bc878.tar.gz
sssd-c391633a8cc03f0fc3be0b7c424b28acf94bc878.tar.xz
sssd-c391633a8cc03f0fc3be0b7c424b28acf94bc878.zip
Add simple reference counting wrappers for talloc
Diffstat (limited to 'server/util')
-rw-r--r--server/util/refcount.c88
-rw-r--r--server/util/refcount.h39
2 files changed, 127 insertions, 0 deletions
diff --git a/server/util/refcount.c b/server/util/refcount.c
new file mode 100644
index 000000000..735170d1b
--- /dev/null
+++ b/server/util/refcount.c
@@ -0,0 +1,88 @@
+/*
+ SSSD
+
+ Simple reference counting wrappers for talloc.
+
+ Authors:
+ Martin Nagy <mnagy@redhat.com>
+
+ Copyright (C) Red Hat, Inc 2009
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <talloc.h>
+
+#include "refcount.h"
+#include "util/util.h"
+
+struct wrapper {
+ int *refcount;
+ void *ptr;
+};
+
+static int
+refcount_destructor(struct wrapper *wrapper)
+{
+ (*wrapper->refcount)--;
+ if (*wrapper->refcount == 0) {
+ talloc_free(wrapper->ptr);
+ };
+
+ return 0;
+}
+
+void *
+_rc_alloc(const void *context, size_t size, size_t refcount_offset,
+ const char *type_name)
+{
+ struct wrapper *wrapper;
+
+ wrapper = talloc(context, struct wrapper);
+ if (wrapper == NULL) {
+ return NULL;
+ }
+
+ wrapper->ptr = talloc_named_const(NULL, size, type_name);
+ if (wrapper->ptr == NULL) {
+ talloc_free(wrapper);
+ return NULL;
+ };
+
+ wrapper->refcount = (int *)((char *)wrapper->ptr + refcount_offset);
+ *wrapper->refcount = 1;
+
+ talloc_set_destructor(wrapper, refcount_destructor);
+
+ return wrapper->ptr;
+}
+
+void *
+_rc_reference(const void *context, size_t refcount_offset, void *source)
+{
+ struct wrapper *wrapper;
+
+ wrapper = talloc(context, struct wrapper);
+ if (wrapper == NULL) {
+ return NULL;
+ }
+
+ wrapper->ptr = source;
+ wrapper->refcount = (int *)((char *)wrapper->ptr + refcount_offset);
+ (*wrapper->refcount)++;
+
+ talloc_set_destructor(wrapper, refcount_destructor);
+
+ return wrapper->ptr;
+}
diff --git a/server/util/refcount.h b/server/util/refcount.h
new file mode 100644
index 000000000..cc99a1731
--- /dev/null
+++ b/server/util/refcount.h
@@ -0,0 +1,39 @@
+#ifndef __REFCOUNT_H__
+#define __REFCOUNT_H__
+
+#include <stddef.h>
+
+#define REFCOUNT_MEMBER_NAME DO_NOT_TOUCH_THIS_MEMBER_refcount
+
+/*
+ * Include this member in your structure in order to be able to use it with
+ * the refcount_* functions.
+ */
+#define REFCOUNT_COMMON int REFCOUNT_MEMBER_NAME
+
+/*
+ * Allocate a new structure that uses reference counting. The resulting pointer
+ * returned. You must not free the returned pointer manually. It will be freed
+ * when 'ctx' is freed with talloc_free() and no other references are left.
+ */
+#define rc_alloc(ctx, type) \
+ (type *)_rc_alloc(ctx, sizeof(type), offsetof(type, REFCOUNT_MEMBER_NAME), \
+ #type)
+
+/*
+ * Increment the reference count of 'src' and return it back if we are
+ * successful. The reference count will be decremented after 'ctx' has been
+ * released by talloc_free(). The function will return NULL in case of failure.
+ */
+#define rc_reference(ctx, type, src) \
+ (type *)_rc_reference(ctx, offsetof(type, REFCOUNT_MEMBER_NAME), src)
+
+/*
+ * These functions should not be used directly. Use the above macros instead.
+ */
+void *_rc_alloc(const void *context, size_t size, size_t refcount_offset,
+ const char *type_name);
+void *_rc_reference(const void *context, size_t refcount_offset, void *source);
+
+
+#endif /* !__REFCOUNT_H__ */