summaryrefslogtreecommitdiffstats
path: root/libglusterfs/src/refcount.h
diff options
context:
space:
mode:
authorNiels de Vos <ndevos@redhat.com>2015-05-31 15:16:41 +0200
committerNiels de Vos <ndevos@redhat.com>2015-06-20 05:01:43 -0700
commitea1d2b0045e2c2ad82a2162a58f9fc36f9d07b20 (patch)
tree986f6c3039c26e0d4547b1ddde8b0f324270113d /libglusterfs/src/refcount.h
parentf460d1c9a2d83b24500c574aabce75438bdc8f9d (diff)
core: add "gf_ref_t" for common refcounting structures
Checks for compiler supported atomic operations comes from client_t.h. An example usage of this change can be found in adding reference counting to "struct auth_cache_entry" in http://review.gluster.org/11023 Basic usage looks like this: #include "refcount.h" struct my_struct { GF_REF_DECL; ... /* more members */ } void my_destructor (void *data) { struct my_struct *my_ptr = (struct my_struct *) data; ... /* do some more cleanups */ GF_FREE (my_ptr); } void init_ptr (struct parent *parent) { struct my_struct *my_ptr = malloc (sizeof (struct my_struct)); GF_REF_INIT (my_ptr, my_destructor); /* refcount is set to 1 */ ... /* my_ptr probably gets added to some parent structure */ parent_add_ptr (parent, my_ptr); } void do_something (struct parent *parent) { struct my_struct *my_ptr = NULL; /* likely need to lock parent, depends on its access pattern */ my_ptr = parent_remove_first_ptr (parent); /* unlock parent */ ... /* do something */ GF_REF_PUT (my_ptr); /* calls my_destructor on refcount = 0 */ } URL: http://thread.gmane.org/gmane.comp.file-systems.gluster.devel/11202 Change-Id: Idb98a5861a44c31676108ed8876db12c320912ef BUG: 1228157 Signed-off-by: Niels de Vos <ndevos@redhat.com> Reviewed-on: http://review.gluster.org/11022 Reviewed-by: Xavier Hernandez <xhernandez@datalab.es> Reviewed-by: Krishnan Parthasarathi <kparthas@redhat.com> Tested-by: Gluster Build System <jenkins@build.gluster.com> Tested-by: NetBSD Build System <jenkins@build.gluster.org>
Diffstat (limited to 'libglusterfs/src/refcount.h')
-rw-r--r--libglusterfs/src/refcount.h103
1 files changed, 103 insertions, 0 deletions
diff --git a/libglusterfs/src/refcount.h b/libglusterfs/src/refcount.h
new file mode 100644
index 00000000000..19fa77de9aa
--- /dev/null
+++ b/libglusterfs/src/refcount.h
@@ -0,0 +1,103 @@
+/*
+ Copyright (c) 2015 Red Hat, Inc. <http://www.redhat.com>
+ This file is part of GlusterFS.
+
+ This file is licensed to you under your choice of the GNU Lesser
+ General Public License, version 3 or any later version (LGPLv3 or
+ later), or the GNU General Public License, version 2 (GPLv2), in all
+ cases as published by the Free Software Foundation.
+*/
+
+#ifndef _REFCOUNT_H
+#define _REFCOUNT_H
+
+/* check for compiler support for __sync_*_and_fetch()
+ *
+ * a more comprehensive feature test is shown at
+ * http://lists.iptel.org/pipermail/semsdev/2010-October/005075.html
+ * this is sufficient for RHEL5 i386 builds
+ */
+#if (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 1)) && !defined(__i386__)
+#undef REFCOUNT_NEEDS_LOCK
+#else
+#define REFCOUNT_NEEDS_LOCK
+#include "locking.h"
+#endif /* compiler support for __sync_*_and_fetch() */
+
+typedef void (*gf_ref_release_t)(void *data);
+
+struct _gf_ref_t {
+#ifdef REFCOUNT_NEEDS_LOCK
+ gf_lock_t lk; /* lock for atomically adjust cnt */
+#endif
+ unsigned int cnt; /* number of users, free on 0 */
+
+ gf_ref_release_t release; /* cleanup when cnt == 0 */
+ void *data; /* parameter passed to release() */
+};
+typedef struct _gf_ref_t gf_ref_t;
+
+
+/* _gf_ref_get -- increase the refcount and return the number of references
+ *
+ * @return: greater then 0 when a reference was taken, 0 when not
+ */
+unsigned int
+_gf_ref_get (gf_ref_t *ref);
+
+/* _gf_ref_put -- decrease the refcount and return the number of references
+ *
+ * @return: greater then 0 when there are still references, 0 when cleanup
+ * should be done
+ */
+unsigned int
+_gf_ref_put (gf_ref_t *ref);
+
+/* _gf_ref_init -- initalize an embedded refcount object
+ *
+ * @release: function to call when the refcount == 0
+ * @data: parameter to be passed to @release
+ */
+void
+_gf_ref_init (gf_ref_t *ref, gf_ref_release_t release, void *data);
+
+
+/*
+ * Strong suggestion to use the simplified GF_REF_* API.
+ */
+
+/* GF_REF_DECL -- declaration to put inside your structure
+ *
+ * Example:
+ * struct my_struct {
+ * GF_REF_DECL;
+ *
+ * ... // additional members
+ * };
+ */
+#define GF_REF_DECL gf_ref_t _ref
+
+/* GF_REF_INIT -- initialize a GF_REF_DECL structure
+ *
+ * @p: allocated structure with GF_REF_DECL
+ * @d: destructor to call once refcounting reaches 0
+ *
+ * Sets the refcount to 1.
+ */
+#define GF_REF_INIT(p, d) _gf_ref_init (&p->_ref, d, p)
+
+/* GF_REF_GET -- increase the refcount of a GF_REF_DECL structure
+ *
+ * @return: greater then 0 when a reference was taken, 0 when not
+ */
+#define GF_REF_GET(p) _gf_ref_get (&p->_ref)
+
+/* GF_REF_PUT -- decrease the refcount of a GF_REF_DECL structure
+ *
+ * @return: greater then 0 when there are still references, 0 when cleanup
+ * should be done
+ */
+#define GF_REF_PUT(p) _gf_ref_put (&p->_ref)
+
+
+#endif /* _REFCOUNT_H */