grefcount.h 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. /* grefcount.h: Reference counting
  2. *
  3. * Copyright 2018 Emmanuele Bassi
  4. *
  5. * SPDX-License-Identifier: LGPL-2.1-or-later
  6. *
  7. * This library is free software; you can redistribute it and/or
  8. * modify it under the terms of the GNU Lesser General Public
  9. * License as published by the Free Software Foundation; either
  10. * version 2.1 of the License, or (at your option) any later version.
  11. *
  12. * This library is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  15. * Lesser General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU Lesser General Public
  18. * License along with this library; if not, see <http://www.gnu.org/licenses/>.
  19. */
  20. #ifndef __GREFCOUNT_H__
  21. #define __GREFCOUNT_H__
  22. #if !defined (__GLIB_H_INSIDE__) && !defined (GLIB_COMPILATION)
  23. #error "Only <glib.h> can be included directly."
  24. #endif
  25. #include <glib/gatomic.h>
  26. #include <glib/gtypes.h>
  27. G_BEGIN_DECLS
  28. GLIB_AVAILABLE_IN_2_58
  29. void g_ref_count_init (grefcount *rc);
  30. GLIB_AVAILABLE_IN_2_58
  31. void g_ref_count_inc (grefcount *rc);
  32. GLIB_AVAILABLE_IN_2_58
  33. gboolean g_ref_count_dec (grefcount *rc);
  34. GLIB_AVAILABLE_IN_2_58
  35. gboolean g_ref_count_compare (grefcount *rc,
  36. gint val);
  37. GLIB_AVAILABLE_IN_2_58
  38. void g_atomic_ref_count_init (gatomicrefcount *arc);
  39. GLIB_AVAILABLE_IN_2_58
  40. void g_atomic_ref_count_inc (gatomicrefcount *arc);
  41. GLIB_AVAILABLE_IN_2_58
  42. gboolean g_atomic_ref_count_dec (gatomicrefcount *arc);
  43. GLIB_AVAILABLE_IN_2_58
  44. gboolean g_atomic_ref_count_compare (gatomicrefcount *arc,
  45. gint val);
  46. /**
  47. * G_REF_COUNT_INIT:
  48. *
  49. * Evaluates to the initial reference count for `grefcount`.
  50. *
  51. * This macro is useful for initializing `grefcount` fields inside
  52. * structures, for instance:
  53. *
  54. * |[<!-- language="C" -->
  55. * typedef struct {
  56. * grefcount ref_count;
  57. * char *name;
  58. * char *address;
  59. * } Person;
  60. *
  61. * static const Person default_person = {
  62. * .ref_count = G_REF_COUNT_INIT,
  63. * .name = "Default name",
  64. * .address = "Default address",
  65. * };
  66. * ]|
  67. *
  68. * Since: 2.78
  69. */
  70. #define G_REF_COUNT_INIT -1 \
  71. GLIB_AVAILABLE_MACRO_IN_2_78
  72. /**
  73. * G_ATOMIC_REF_COUNT_INIT:
  74. *
  75. * Evaluates to the initial reference count for `gatomicrefcount`.
  76. *
  77. * This macro is useful for initializing `gatomicrefcount` fields inside
  78. * structures, for instance:
  79. *
  80. * |[<!-- language="C" -->
  81. * typedef struct {
  82. * gatomicrefcount ref_count;
  83. * char *name;
  84. * char *address;
  85. * } Person;
  86. *
  87. * static const Person default_person = {
  88. * .ref_count = G_ATOMIC_REF_COUNT_INIT,
  89. * .name = "Default name",
  90. * .address = "Default address",
  91. * };
  92. * ]|
  93. *
  94. * Since: 2.78
  95. */
  96. #define G_ATOMIC_REF_COUNT_INIT 1 \
  97. GLIB_AVAILABLE_MACRO_IN_2_78
  98. /* On GCC we can use __extension__ to inline the API without using
  99. * ancillary functions; we only do this when disabling checks, as
  100. * it disables warnings when saturating the reference counters
  101. */
  102. #if defined(__GNUC__) && defined(G_DISABLE_CHECKS)
  103. # define g_ref_count_init(rc) \
  104. (G_GNUC_EXTENSION ({ \
  105. G_STATIC_ASSERT (sizeof *(rc) == sizeof (grefcount)); \
  106. (void) (0 ? *(rc) ^ *(rc) : 1); \
  107. *(rc) = -1; \
  108. }))
  109. # define g_ref_count_inc(rc) \
  110. (G_GNUC_EXTENSION ({ \
  111. G_STATIC_ASSERT (sizeof *(rc) == sizeof (grefcount)); \
  112. (void) (0 ? *(rc) ^ *(rc) : 1); \
  113. if (*(rc) == G_MININT) ; else { \
  114. *(rc) -= 1; \
  115. } \
  116. }))
  117. # define g_ref_count_dec(rc) \
  118. (G_GNUC_EXTENSION ({ \
  119. G_STATIC_ASSERT (sizeof *(rc) == sizeof (grefcount)); \
  120. grefcount __rc = *(rc); \
  121. __rc += 1; \
  122. if (__rc == 0) ; else { \
  123. *(rc) = __rc; \
  124. } \
  125. (gboolean) (__rc == 0); \
  126. }))
  127. # define g_ref_count_compare(rc,val) \
  128. (G_GNUC_EXTENSION ({ \
  129. G_STATIC_ASSERT (sizeof *(rc) == sizeof (grefcount)); \
  130. (void) (0 ? *(rc) ^ (val) : 1); \
  131. (gboolean) (*(rc) == -(val)); \
  132. }))
  133. # define g_atomic_ref_count_init(rc) \
  134. (G_GNUC_EXTENSION ({ \
  135. G_STATIC_ASSERT (sizeof *(rc) == sizeof (gatomicrefcount)); \
  136. (void) (0 ? *(rc) ^ *(rc) : 1); \
  137. *(rc) = 1; \
  138. }))
  139. # define g_atomic_ref_count_inc(rc) \
  140. (G_GNUC_EXTENSION ({ \
  141. G_STATIC_ASSERT (sizeof *(rc) == sizeof (gatomicrefcount)); \
  142. (void) (0 ? *(rc) ^ *(rc) : 1); \
  143. (void) (g_atomic_int_get (rc) == G_MAXINT ? 0 : g_atomic_int_inc ((rc))); \
  144. }))
  145. # define g_atomic_ref_count_dec(rc) \
  146. (G_GNUC_EXTENSION ({ \
  147. G_STATIC_ASSERT (sizeof *(rc) == sizeof (gatomicrefcount)); \
  148. (void) (0 ? *(rc) ^ *(rc) : 1); \
  149. g_atomic_int_dec_and_test ((rc)); \
  150. }))
  151. # define g_atomic_ref_count_compare(rc,val) \
  152. (G_GNUC_EXTENSION ({ \
  153. G_STATIC_ASSERT (sizeof *(rc) == sizeof (gatomicrefcount)); \
  154. (void) (0 ? *(rc) ^ (val) : 1); \
  155. (gboolean) (g_atomic_int_get (rc) == (val)); \
  156. }))
  157. #endif /* __GNUC__ && G_DISABLE_CHECKS */
  158. G_END_DECLS
  159. #endif /* __GREFCOUNT_H__ */