Justus Winter, le Tue 13 May 2014 21:02:54 +0200, a écrit : > * include/refcount.h: New file.
Ack. > --- > include/refcount.h | 193 > +++++++++++++++++++++++++++++++++++++++++++++++++++++ > 1 file changed, 193 insertions(+) > create mode 100644 include/refcount.h > > diff --git a/include/refcount.h b/include/refcount.h > new file mode 100644 > index 0000000..0816220 > --- /dev/null > +++ b/include/refcount.h > @@ -0,0 +1,193 @@ > +/* Lock-less reference counting primitives > + > + Copyright (C) 2014 Free Software Foundation, Inc. > + > + Written by Justus Winter <4win...@informatik.uni-hamburg.de> > + > + This file is part of the GNU Hurd. > + > + The GNU Hurd 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 2, or (at > + your option) any later version. > + > + The GNU Hurd 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 the GNU Hurd. If not, see <http://www.gnu.org/licenses/>. */ > + > +#ifndef _HURD_REFCOUNT_H_ > +#define _HURD_REFCOUNT_H_ > + > +#include <assert.h> > +#include <stdint.h> > + > +/* Simple reference counting. */ > + > +/* An opaque type. You must not access these values directly. */ > +typedef unsigned int refcount_t; > + > +/* Initialize REF with REFERENCES. */ > +static inline void > +refcount_init (refcount_t *ref, unsigned int references) > +{ > + *ref = references; > +} > + > +/* Increment REF. Return the result of the operation. This function > + uses atomic operations. It is not required to serialize calls to > + this function. */ > +static inline unsigned int > +refcount_ref (refcount_t *ref) > +{ > + unsigned int r; > + r = __atomic_add_fetch (ref, 1, __ATOMIC_RELAXED); > + assert (r != UINT_MAX); > + return r; > +} > + > +/* Decrement REF. Return the result of the operation. This function > + uses atomic operations. It is not required to serialize calls to > + this function. */ > +static inline unsigned int > +refcount_deref (refcount_t *ref) > +{ > + unsigned int r; > + r = __atomic_sub_fetch (ref, 1, __ATOMIC_RELAXED); > + assert (r != UINT_MAX); > + return r; > +} > + > +/* Return REF. This function uses atomic operations. It is not > + required to serialize calls to this function. */ > +static inline unsigned int > +refcount_references (refcount_t *ref) > +{ > + return __atomic_load_n (ref, __ATOMIC_RELAXED); > +} > + > +/* Reference counting with weak references. */ > + > +/* An opaque type. You must not access these values directly. */ > +typedef union _references refcounts_t; > + > +/* Instead, the functions manipulating refcounts_t values write the > + results into this kind of objects. */ > +struct references { > + uint32_t hard; > + uint32_t weak; > +}; > + > +/* We use a union to convert struct reference values to uint64_t which > + we can manipulate atomically. While this behavior is not > + guaranteed by the C standard, it is supported by all major > + compilers. */ > +union _references { > + struct references references; > + uint64_t value; > +}; > + > +/* Initialize REF with HARD and WEAK references. */ > +static inline void > +refcounts_init (refcounts_t *ref, uint32_t hard, uint32_t weak) > +{ > + ref->references = (struct references) { .hard = hard, .weak = weak }; > +} > + > +/* Increment the hard reference count of REF. If RESULT is not NULL, > + the result of the operation is written there. This function uses > + atomic operations. It is not required to serialize calls to this > + function. */ > +static inline void > +refcounts_ref (refcounts_t *ref, struct references *result) > +{ > + const union _references op = { .references = { .hard = 1 } }; > + union _references r; > + r.value = __atomic_add_fetch (&ref->value, op.value, __ATOMIC_RELAXED); > + assert (r.references.hard != UINT32_MAX); > + if (result) > + *result = r.references; > +} > + > +/* Decrement the hard reference count of REF. If RESULT is not NULL, > + the result of the operation is written there. This function uses > + atomic operations. It is not required to serialize calls to this > + function. */ > +static inline void > +refcounts_deref (refcounts_t *ref, struct references *result) > +{ > + const union _references op = { .references = { .hard = 1 } }; > + union _references r; > + r.value = __atomic_sub_fetch (&ref->value, op.value, __ATOMIC_RELAXED); > + assert (r.references.hard != UINT32_MAX); > + if (result) > + *result = r.references; > +} > + > +/* Increment the weak reference count of REF. If RESULT is not NULL, > + the result of the operation is written there. This function uses > + atomic operations. It is not required to serialize calls to this > + function. */ > +static inline void > +refcounts_ref_weak (refcounts_t *ref, struct references *result) > +{ > + const union _references op = { .references = { .weak = 1 } }; > + union _references r; > + r.value = __atomic_add_fetch (&ref->value, op.value, __ATOMIC_RELAXED); > + assert (r.references.weak != UINT32_MAX); > + if (result) > + *result = r.references; > +} > + > +/* Decrement the weak reference count of REF. If RESULT is not NULL, > + the result of the operation is written there. This function uses > + atomic operations. It is not required to serialize calls to this > + function. */ > +static inline void > +refcounts_deref_weak (refcounts_t *ref, struct references *result) > +{ > + const union _references op = { .references = { .weak = 1 } }; > + union _references r; > + r.value = __atomic_sub_fetch (&ref->value, op.value, __ATOMIC_RELAXED); > + assert (r.references.weak != UINT32_MAX); > + if (result) > + *result = r.references; > +} > + > +/* Store the current reference counts of REF in RESULT. This function > + uses atomic operations. It is not required to serialize calls to > + this function. */ > +static inline void > +refcounts_references (refcounts_t *ref, struct references *result) > +{ > + union _references r; > + r.value =__atomic_load_n (&ref->value, __ATOMIC_RELAXED); > + *result = r.references; > +} > + > +/* Return the hard reference count of REF. This function uses atomic > + operations. It is not required to serialize calls to this > + function. */ > +static inline uint32_t > +refcounts_hard_references (refcounts_t *ref) > +{ > + struct references result; > + refcounts_references (ref, &result); > + return result.hard; > +} > + > +/* Return the weak reference count of REF. This function uses atomic > + operations. It is not required to serialize calls to this > + function. */ > +static inline uint32_t > +refcounts_weak_references (refcounts_t *ref) > +{ > + struct references result; > + refcounts_references (ref, &result); > + return result.weak; > +} > + > +#endif /* _HURD_REFCOUNT_H_ */ > -- > 2.0.0.rc0 > -- Samuel * x remarque qu'avec un peu de volonté, on peut faire du code de porc dans d'importe quel langage Turing-complet -+- x sur #ens-mim - codons porc -+-