xref: /openbsd-src/usr.bin/dig/lib/isc/include/isc/refcount.h (revision b9558d14c675017cf470d7469a47201d05e39444)
1 /*
2  * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
3  *
4  * Permission to use, copy, modify, and/or distribute this software for any
5  * purpose with or without fee is hereby granted, provided that the above
6  * copyright notice and this permission notice appear in all copies.
7  *
8  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
9  * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
10  * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
11  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
12  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
13  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
14  * PERFORMANCE OF THIS SOFTWARE.
15  */
16 
17 /* $Id: refcount.h,v 1.3 2020/02/25 05:00:43 jsg Exp $ */
18 
19 #ifndef ISC_REFCOUNT_H
20 #define ISC_REFCOUNT_H 1
21 
22 #include <isc/assertions.h>
23 #include <isc/error.h>
24 #include <isc/types.h>
25 
26 /*! \file isc/refcount.h
27  * \brief Implements a locked reference counter.
28  *
29  * These functions may actually be
30  * implemented using macros, and implementations of these macros are below.
31  * The isc_refcount_t type should not be accessed directly, as its contents
32  * depend on the implementation.
33  */
34 
35 /*
36  * Function prototypes
37  */
38 
39 /*
40  * isc_result_t
41  * isc_refcount_init(isc_refcount_t *ref, unsigned int n);
42  *
43  * Initialize the reference counter.  There will be 'n' initial references.
44  *
45  * Requires:
46  *	ref != NULL
47  */
48 
49 /*
50  * void
51  * isc_refcount_destroy(isc_refcount_t *ref);
52  *
53  * Destroys a reference counter.
54  *
55  * Requires:
56  *	ref != NULL
57  *	The number of references is 0.
58  */
59 
60 /*
61  * void
62  * isc_refcount_increment(isc_refcount_t *ref, unsigned int *targetp);
63  * isc_refcount_increment0(isc_refcount_t *ref, unsigned int *targetp);
64  *
65  * Increments the reference count, returning the new value in targetp if it's
66  * not NULL.  The reference counter typically begins with the initial counter
67  * of 1, and will be destroyed once the counter reaches 0.  Thus,
68  * isc_refcount_increment() additionally requires the previous counter be
69  * larger than 0 so that an error which violates the usage can be easily
70  * caught.  isc_refcount_increment0() does not have this restriction.
71  *
72  * Requires:
73  *	ref != NULL.
74  */
75 
76 /*
77  * void
78  * isc_refcount_decrement(isc_refcount_t *ref, unsigned int *targetp);
79  *
80  * Decrements the reference count,  returning the new value in targetp if it's
81  * not NULL.
82  *
83  * Requires:
84  *	ref != NULL.
85  */
86 
87 /*
88  * Sample implementations
89  */
90 
91 typedef struct isc_refcount {
92 	int refs;
93 } isc_refcount_t;
94 
95 #define isc_refcount_destroy(rp) ISC_REQUIRE((rp)->refs == 0)
96 #define isc_refcount_current(rp) ((unsigned int)((rp)->refs))
97 
98 #define isc_refcount_increment0(rp, tp)					\
99 	do {								\
100 		unsigned int *_tmp = (unsigned int *)(tp);		\
101 		int _n = ++(rp)->refs;					\
102 		if (_tmp != NULL)					\
103 			*_tmp = _n;					\
104 	} while (0)
105 
106 #define isc_refcount_increment(rp, tp)					\
107 	do {								\
108 		unsigned int *_tmp = (unsigned int *)(tp);		\
109 		int _n;							\
110 		ISC_REQUIRE((rp)->refs > 0);				\
111 		_n = ++(rp)->refs;					\
112 		if (_tmp != NULL)					\
113 			*_tmp = _n;					\
114 	} while (0)
115 
116 #define isc_refcount_decrement(rp, tp)					\
117 	do {								\
118 		unsigned int *_tmp = (unsigned int *)(tp);		\
119 		int _n;							\
120 		ISC_REQUIRE((rp)->refs > 0);				\
121 		_n = --(rp)->refs;					\
122 		if (_tmp != NULL)					\
123 			*_tmp = _n;					\
124 	} while (0)
125 
126 isc_result_t
127 isc_refcount_init(isc_refcount_t *ref, unsigned int n);
128 
129 #endif /* ISC_REFCOUNT_H */
130