#ifndef ISC_REFCOUNT_H
#define ISC_REFCOUNT_H 1
#include <isc/atomic.h>
#include <isc/lang.h>
#include <isc/mutex.h>
#include <isc/platform.h>
#include <isc/types.h>
#include <isc/util.h>
ISC_LANG_BEGINDECLS
#ifdef ISC_PLATFORM_USETHREADS
#ifdef ISC_PLATFORM_HAVEXADD
#define ISC_REFCOUNT_HAVEATOMIC 1
typedef struct isc_refcount {
isc_int32_t refs;
} isc_refcount_t;
#define isc_refcount_destroy(rp) (REQUIRE((rp)->refs == 0))
#define isc_refcount_current(rp) ((unsigned int)((rp)->refs))
#define isc_refcount_increment0(rp, tp) \
do { \
unsigned int *_tmp = (unsigned int *)(tp); \
isc_int32_t prev; \
prev = isc_atomic_xadd(&(rp)->refs, 1); \
if (_tmp != NULL) \
*_tmp = prev + 1; \
} while (0)
#define isc_refcount_increment(rp, tp) \
do { \
unsigned int *_tmp = (unsigned int *)(tp); \
isc_int32_t prev; \
prev = isc_atomic_xadd(&(rp)->refs, 1); \
REQUIRE(prev > 0); \
if (_tmp != NULL) \
*_tmp = prev + 1; \
} while (0)
#define isc_refcount_decrement(rp, tp) \
do { \
unsigned int *_tmp = (unsigned int *)(tp); \
isc_int32_t prev; \
prev = isc_atomic_xadd(&(rp)->refs, -1); \
REQUIRE(prev > 0); \
if (_tmp != NULL) \
*_tmp = prev - 1; \
} while (0)
#else
typedef struct isc_refcount {
int refs;
isc_mutex_t lock;
} isc_refcount_t;
#define isc_refcount_destroy(rp) \
do { \
REQUIRE((rp)->refs == 0); \
DESTROYLOCK(&(rp)->lock); \
} while (0)
#define isc_refcount_current(rp) ((unsigned int)((rp)->refs))
#define isc_refcount_increment0(rp, tp) \
do { \
unsigned int *_tmp = (unsigned int *)(tp); \
LOCK(&(rp)->lock); \
++((rp)->refs); \
if (_tmp != NULL) \
*_tmp = ((rp)->refs); \
UNLOCK(&(rp)->lock); \
} while (0)
#define isc_refcount_increment(rp, tp) \
do { \
unsigned int *_tmp = (unsigned int *)(tp); \
LOCK(&(rp)->lock); \
REQUIRE((rp)->refs > 0); \
++((rp)->refs); \
if (_tmp != NULL) \
*_tmp = ((rp)->refs); \
UNLOCK(&(rp)->lock); \
} while (0)
#define isc_refcount_decrement(rp, tp) \
do { \
unsigned int *_tmp = (unsigned int *)(tp); \
LOCK(&(rp)->lock); \
REQUIRE((rp)->refs > 0); \
--((rp)->refs); \
if (_tmp != NULL) \
*_tmp = ((rp)->refs); \
UNLOCK(&(rp)->lock); \
} while (0)
#endif
#else
typedef struct isc_refcount {
int refs;
} isc_refcount_t;
#define isc_refcount_destroy(rp) (REQUIRE((rp)->refs == 0))
#define isc_refcount_current(rp) ((unsigned int)((rp)->refs))
#define isc_refcount_increment0(rp, tp) \
do { \
unsigned int *_tmp = (unsigned int *)(tp); \
int _n = ++(rp)->refs; \
if (_tmp != NULL) \
*_tmp = _n; \
} while (0)
#define isc_refcount_increment(rp, tp) \
do { \
unsigned int *_tmp = (unsigned int *)(tp); \
int _n; \
REQUIRE((rp)->refs > 0); \
_n = ++(rp)->refs; \
if (_tmp != NULL) \
*_tmp = _n; \
} while (0)
#define isc_refcount_decrement(rp, tp) \
do { \
unsigned int *_tmp = (unsigned int *)(tp); \
int _n; \
REQUIRE((rp)->refs > 0); \
_n = --(rp)->refs; \
if (_tmp != NULL) \
*_tmp = _n; \
} while (0)
#endif
isc_result_t
isc_refcount_init(isc_refcount_t *ref, unsigned int n);
ISC_LANG_ENDDECLS
#endif