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