blob: 7f489abc981967b051397a082df8aaf4e0ec24c8 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
|
#ifndef _IPXE_REFCNT_H
#define _IPXE_REFCNT_H
/** @file
*
* Reference counting
*
*/
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <stddef.h>
#include <assert.h>
/**
* A reference counter
*
* This data structure is designed to be embedded within a
* reference-counted object.
*
* Reference-counted objects are freed when their reference count
* drops below zero. This means that a freshly allocated-and-zeroed
* reference-counted object will be freed on the first call to
* ref_put().
*/
struct refcnt {
/** Current reference count
*
* When this count is decremented below zero, the free()
* method will be called.
*/
int count;
/** Free containing object
*
* This method is called when the reference count is
* decremented below zero.
*
* If this method is left NULL, the standard library free()
* function will be called. The upshot of this is that you
* may omit the free() method if the @c refcnt object is the
* first element of your reference-counted struct.
*/
void ( * free ) ( struct refcnt *refcnt );
};
/**
* Initialise a reference counter
*
* @v refcnt Reference counter
* @v free Freeing function
*/
static inline __attribute__ (( always_inline )) void
ref_init ( struct refcnt *refcnt,
void ( * free ) ( struct refcnt *refcnt ) ) {
refcnt->free = free;
}
/**
* Initialise a reference counter
*
* @v refcnt Reference counter
* @v free Free containing object
*/
#define ref_init( refcnt, free ) do { \
if ( __builtin_constant_p ( (free) ) && ( (free) == NULL ) ) { \
/* Skip common case of no initialisation required */ \
} else { \
ref_init ( (refcnt), (free) ); \
} \
} while ( 0 )
/**
* Initialise a static reference counter
*
* @v free_fn Free containing object
*/
#define REF_INIT( free_fn ) { \
.free = free_fn, \
}
extern void ref_increment ( struct refcnt *refcnt );
extern void ref_decrement ( struct refcnt *refcnt );
/**
* Get additional reference to object
*
* @v refcnt Reference counter, or NULL
* @ret refcnt Reference counter
*
* If @c refcnt is NULL, no action is taken.
*/
#define ref_get( refcnt ) ( { \
if ( refcnt ) \
assert ( (refcnt)->count >= 0 ); \
ref_increment ( refcnt ); \
(refcnt); } )
/**
* Drop reference to object
*
* @v refcnt Reference counter, or NULL
* @ret refcnt Reference counter
*
* If @c refcnt is NULL, no action is taken.
*/
#define ref_put( refcnt ) do { \
if ( refcnt ) \
assert ( (refcnt)->count >= 0 ); \
ref_decrement ( refcnt ); \
} while ( 0 )
extern void ref_no_free ( struct refcnt *refcnt );
#endif /* _IPXE_REFCNT_H */
|