You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

refcnt.h 2.6KB

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