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