PageRenderTime 15ms CodeModel.GetById 8ms app.highlight 3ms RepoModel.GetById 1ms app.codeStats 0ms

/contrib/bind9/lib/isc/include/isc/refcount.h

https://bitbucket.org/freebsd/freebsd-head/
C++ Header | 233 lines | 120 code | 35 blank | 78 comment | 31 complexity | a00ff0b684f4b42f4404c79e897c7c97 MD5 | raw file
  1/*
  2 * Copyright (C) 2004-2007, 2009  Internet Systems Consortium, Inc. ("ISC")
  3 * Copyright (C) 2001, 2003  Internet Software Consortium.
  4 *
  5 * Permission to use, copy, modify, and/or distribute this software for any
  6 * purpose with or without fee is hereby granted, provided that the above
  7 * copyright notice and this permission notice appear in all copies.
  8 *
  9 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
 10 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
 11 * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
 12 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
 13 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
 14 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 15 * PERFORMANCE OF THIS SOFTWARE.
 16 */
 17
 18/* $Id: refcount.h,v 1.17 2009/09/29 23:48:04 tbox Exp $ */
 19
 20#ifndef ISC_REFCOUNT_H
 21#define ISC_REFCOUNT_H 1
 22
 23#include <isc/atomic.h>
 24#include <isc/lang.h>
 25#include <isc/mutex.h>
 26#include <isc/platform.h>
 27#include <isc/types.h>
 28#include <isc/util.h>
 29
 30/*! \file isc/refcount.h
 31 * \brief Implements a locked reference counter.
 32 *
 33 * These functions may actually be
 34 * implemented using macros, and implementations of these macros are below.
 35 * The isc_refcount_t type should not be accessed directly, as its contents
 36 * depend on the implementation.
 37 */
 38
 39ISC_LANG_BEGINDECLS
 40
 41/*
 42 * Function prototypes
 43 */
 44
 45/*
 46 * isc_result_t
 47 * isc_refcount_init(isc_refcount_t *ref, unsigned int n);
 48 *
 49 * Initialize the reference counter.  There will be 'n' initial references.
 50 *
 51 * Requires:
 52 *	ref != NULL
 53 */
 54
 55/*
 56 * void
 57 * isc_refcount_destroy(isc_refcount_t *ref);
 58 *
 59 * Destroys a reference counter.
 60 *
 61 * Requires:
 62 *	ref != NULL
 63 *	The number of references is 0.
 64 */
 65
 66/*
 67 * void
 68 * isc_refcount_increment(isc_refcount_t *ref, unsigned int *targetp);
 69 * isc_refcount_increment0(isc_refcount_t *ref, unsigned int *targetp);
 70 *
 71 * Increments the reference count, returning the new value in targetp if it's
 72 * not NULL.  The reference counter typically begins with the initial counter
 73 * of 1, and will be destroyed once the counter reaches 0.  Thus,
 74 * isc_refcount_increment() additionally requires the previous counter be
 75 * larger than 0 so that an error which violates the usage can be easily
 76 * caught.  isc_refcount_increment0() does not have this restriction.
 77 *
 78 * Requires:
 79 *	ref != NULL.
 80 */
 81
 82/*
 83 * void
 84 * isc_refcount_decrement(isc_refcount_t *ref, unsigned int *targetp);
 85 *
 86 * Decrements the reference count,  returning the new value in targetp if it's
 87 * not NULL.
 88 *
 89 * Requires:
 90 *	ref != NULL.
 91 */
 92
 93
 94/*
 95 * Sample implementations
 96 */
 97#ifdef ISC_PLATFORM_USETHREADS
 98#ifdef ISC_PLATFORM_HAVEXADD
 99
100#define ISC_REFCOUNT_HAVEATOMIC 1
101
102typedef struct isc_refcount {
103	isc_int32_t refs;
104} isc_refcount_t;
105
106#define isc_refcount_destroy(rp) REQUIRE((rp)->refs == 0)
107#define isc_refcount_current(rp) ((unsigned int)((rp)->refs))
108
109#define isc_refcount_increment0(rp, tp)				\
110	do {							\
111		unsigned int *_tmp = (unsigned int *)(tp);	\
112		isc_int32_t prev;				\
113		prev = isc_atomic_xadd(&(rp)->refs, 1);		\
114		if (_tmp != NULL)				\
115			*_tmp = prev + 1;			\
116	} while (0)
117
118#define isc_refcount_increment(rp, tp)				\
119	do {							\
120		unsigned int *_tmp = (unsigned int *)(tp);	\
121		isc_int32_t prev;				\
122		prev = isc_atomic_xadd(&(rp)->refs, 1);		\
123		REQUIRE(prev > 0);				\
124		if (_tmp != NULL)				\
125			*_tmp = prev + 1;			\
126	} while (0)
127
128#define isc_refcount_decrement(rp, tp)				\
129	do {							\
130		unsigned int *_tmp = (unsigned int *)(tp);	\
131		isc_int32_t prev;				\
132		prev = isc_atomic_xadd(&(rp)->refs, -1);	\
133		REQUIRE(prev > 0);				\
134		if (_tmp != NULL)				\
135			*_tmp = prev - 1;			\
136	} while (0)
137
138#else  /* ISC_PLATFORM_HAVEXADD */
139
140typedef struct isc_refcount {
141	int refs;
142	isc_mutex_t lock;
143} isc_refcount_t;
144
145/*% Destroys a reference counter. */
146#define isc_refcount_destroy(rp)			\
147	do {						\
148		REQUIRE((rp)->refs == 0);		\
149		DESTROYLOCK(&(rp)->lock);		\
150	} while (0)
151
152#define isc_refcount_current(rp) ((unsigned int)((rp)->refs))
153
154/*% Increments the reference count, returning the new value in targetp if it's not NULL. */
155#define isc_refcount_increment0(rp, tp)				\
156	do {							\
157		unsigned int *_tmp = (unsigned int *)(tp);	\
158		LOCK(&(rp)->lock);				\
159		++((rp)->refs);					\
160		if (_tmp != NULL)				\
161			*_tmp = ((rp)->refs);			\
162		UNLOCK(&(rp)->lock);				\
163	} while (0)
164
165#define isc_refcount_increment(rp, tp)				\
166	do {							\
167		unsigned int *_tmp = (unsigned int *)(tp);	\
168		LOCK(&(rp)->lock);				\
169		REQUIRE((rp)->refs > 0);			\
170		++((rp)->refs);					\
171		if (_tmp != NULL)				\
172			*_tmp = ((rp)->refs);			\
173		UNLOCK(&(rp)->lock);				\
174	} while (0)
175
176/*% Decrements the reference count,  returning the new value in targetp if it's not NULL. */
177#define isc_refcount_decrement(rp, tp)				\
178	do {							\
179		unsigned int *_tmp = (unsigned int *)(tp);	\
180		LOCK(&(rp)->lock);				\
181		REQUIRE((rp)->refs > 0);			\
182		--((rp)->refs);					\
183		if (_tmp != NULL)				\
184			*_tmp = ((rp)->refs);			\
185		UNLOCK(&(rp)->lock);				\
186	} while (0)
187
188#endif /* ISC_PLATFORM_HAVEXADD */
189#else  /* ISC_PLATFORM_USETHREADS */
190
191typedef struct isc_refcount {
192	int refs;
193} isc_refcount_t;
194
195#define isc_refcount_destroy(rp) REQUIRE((rp)->refs == 0)
196#define isc_refcount_current(rp) ((unsigned int)((rp)->refs))
197
198#define isc_refcount_increment0(rp, tp)					\
199	do {								\
200		unsigned int *_tmp = (unsigned int *)(tp);		\
201		int _n = ++(rp)->refs;					\
202		if (_tmp != NULL)					\
203			*_tmp = _n;					\
204	} while (0)
205
206#define isc_refcount_increment(rp, tp)					\
207	do {								\
208		unsigned int *_tmp = (unsigned int *)(tp);		\
209		int _n;							\
210		REQUIRE((rp)->refs > 0);				\
211		_n = ++(rp)->refs;					\
212		if (_tmp != NULL)					\
213			*_tmp = _n;					\
214	} while (0)
215
216#define isc_refcount_decrement(rp, tp)					\
217	do {								\
218		unsigned int *_tmp = (unsigned int *)(tp);		\
219		int _n;							\
220		REQUIRE((rp)->refs > 0);				\
221		_n = --(rp)->refs;					\
222		if (_tmp != NULL)					\
223			*_tmp = _n;					\
224	} while (0)
225
226#endif /* ISC_PLATFORM_USETHREADS */
227
228isc_result_t
229isc_refcount_init(isc_refcount_t *ref, unsigned int n);
230
231ISC_LANG_ENDDECLS
232
233#endif /* ISC_REFCOUNT_H */