diff options
| author | Niels de Vos <ndevos@redhat.com> | 2015-05-31 15:16:41 +0200 | 
|---|---|---|
| committer | Raghavendra G <rgowdapp@redhat.com> | 2015-06-26 22:26:24 -0700 | 
| commit | d1cfdc873e9c50c0ada8e57b646f14bbeb3c2ef3 (patch) | |
| tree | 3b9481620d430a0c2633fedb7a9673135b3a4b77 /libglusterfs/src/refcount.h | |
| parent | 0857896d2a4daa025fa69db6294f66c5da312fe6 (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: 1235939
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>
(cherry picked from commit ea1d2b0045e2c2ad82a2162a58f9fc36f9d07b20)
Reviewed-on: http://review.gluster.org/11421
Reviewed-by: Raghavendra G <rgowdapp@redhat.com>
Tested-by: Raghavendra G <rgowdapp@redhat.com>
Diffstat (limited to 'libglusterfs/src/refcount.h')
| -rw-r--r-- | libglusterfs/src/refcount.h | 103 | 
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..c8113a2d76b --- /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 */  | 
