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