Merge from vendor branch LESS:
[dragonfly.git] / contrib / bind-9.3 / lib / isc / include / isc / refcount.h
1 /*
2  * Copyright (C) 2004  Internet Systems Consortium, Inc. ("ISC")
3  * Copyright (C) 2001, 2003  Internet Software Consortium.
4  *
5  * Permission to use, copy, modify, and 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.3.2.2.2.2 2004/04/14 05:12:25 marka Exp $ */
19
20 #ifndef ISC_REFCOUNT_H
21 #define ISC_REFCOUNT_H 1
22
23 #include <isc/lang.h>
24 #include <isc/mutex.h>
25 #include <isc/platform.h>
26 #include <isc/types.h>
27 #include <isc/util.h>
28
29 /*
30  * Implements a locked reference counter.  These functions may actually be
31  * implemented using macros, and implementations of these macros are below.
32  * The isc_refcount_t type should not be accessed directly, as its contents
33  * depend on the implementation.
34  */
35
36 ISC_LANG_BEGINDECLS
37
38 /*
39  * Function prototypes
40  */
41
42 /*
43  * void
44  * isc_refcount_init(isc_refcount_t *ref, unsigned int n);
45  *
46  * Initialize the reference counter.  There will be 'n' initial references.
47  *
48  * Requires:
49  *      ref != NULL
50  */
51
52 /*
53  * void
54  * isc_refcount_destroy(isc_refcount_t *ref);
55  *
56  * Destroys a reference counter.
57  *
58  * Requires:
59  *      ref != NULL
60  *      The number of references is 0.
61  */
62
63 /*
64  * void
65  * isc_refcount_increment(isc_refcount_t *ref, unsigned int *targetp);
66  *
67  * Increments the reference count, returning the new value in targetp if it's
68  * not NULL.
69  *
70  * Requires:
71  *      ref != NULL.
72  */
73
74 /*
75  * void
76  * isc_refcount_decrement(isc_refcount_t *ref, unsigned int *targetp);
77  *
78  * Decrements the reference count,  returning the new value in targetp if it's
79  * not NULL.
80  *
81  * Requires:
82  *      ref != NULL.
83  */
84
85
86 /*
87  * Sample implementations
88  */
89 #ifdef ISC_PLATFORM_USETHREADS
90
91 typedef struct isc_refcount {
92         int refs;
93         isc_mutex_t lock;
94 } isc_refcount_t;
95
96 #define isc_refcount_init(rp, n)                        \
97         do {                                            \
98                 isc_result_t _r;                        \
99                 (rp)->refs = (n);                       \
100                 _r = isc_mutex_init(&(rp)->lock);       \
101                 RUNTIME_CHECK(_r == ISC_R_SUCCESS);     \
102         } while (0)
103
104 #define isc_refcount_destroy(rp)                        \
105         do {                                            \
106                 REQUIRE((rp)->refs == 0);               \
107                 DESTROYLOCK(&(rp)->lock);               \
108         } while (0)
109
110 #define isc_refcount_current(rp) ((unsigned int)((rp)->refs))
111
112 #define isc_refcount_increment(rp, tp)                          \
113         do {                                                    \
114                 unsigned int *_tmp = (unsigned int *)(tp);      \
115                 LOCK(&(rp)->lock);                              \
116                 REQUIRE((rp)->refs > 0);                        \
117                 ++((rp)->refs);                                 \
118                 if (_tmp != NULL)                               \
119                         *_tmp = ((rp)->refs);                   \
120                 UNLOCK(&(rp)->lock);                            \
121         } while (0)
122
123 #define isc_refcount_decrement(rp, tp)                          \
124         do {                                                    \
125                 unsigned int *_tmp = (unsigned int *)(tp);      \
126                 LOCK(&(rp)->lock);                              \
127                 REQUIRE((rp)->refs > 0);                        \
128                 --((rp)->refs);                                 \
129                 if (_tmp != NULL)                               \
130                         *_tmp = ((rp)->refs);                   \
131                 UNLOCK(&(rp)->lock);                            \
132         } while (0)
133
134 #else
135
136 typedef struct isc_refcount {
137         int refs;
138 } isc_refcount_t;
139
140 #define isc_refcount_init(rp, n) ((rp)->refs = (n))
141 #define isc_refcount_destroy(rp) (REQUIRE((rp)->refs == 0))
142 #define isc_refcount_current(rp) ((unsigned int)((rp)->refs))
143
144 #define isc_refcount_increment(rp, tp)                                  \
145         do {                                                            \
146                 unsigned int *_tmp = (unsigned int *)(tp);              \
147                 int _n = ++(rp)->refs;                                  \
148                 if (_tmp != NULL)                                       \
149                         *_tmp = _n;                                     \
150         } while (0)
151
152 #define isc_refcount_decrement(rp, tp)                                  \
153         do {                                                            \
154                 unsigned int *_tmp = (unsigned int *)(tp);              \
155                 int _n = --(rp)->refs;                                  \
156                 if (_tmp != NULL)                                       \
157                         *_tmp = _n;                                     \
158         } while (0)
159
160 #endif
161
162 ISC_LANG_ENDDECLS
163
164 #endif /* ISC_REFCOUNT_H */