(root)/
glib-2.79.0/
glib/
grefcount.h
       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  
      21  #ifndef __GREFCOUNT_H__
      22  #define __GREFCOUNT_H__
      23  
      24  #if !defined (__GLIB_H_INSIDE__) && !defined (GLIB_COMPILATION)
      25  #error "Only <glib.h> can be included directly."
      26  #endif
      27  
      28  #include <glib/gatomic.h>
      29  #include <glib/gtypes.h>
      30  
      31  G_BEGIN_DECLS
      32  
      33  GLIB_AVAILABLE_IN_2_58
      34  void            g_ref_count_init                (grefcount       *rc);
      35  GLIB_AVAILABLE_IN_2_58
      36  void            g_ref_count_inc                 (grefcount       *rc);
      37  GLIB_AVAILABLE_IN_2_58
      38  gboolean        g_ref_count_dec                 (grefcount       *rc);
      39  GLIB_AVAILABLE_IN_2_58
      40  gboolean        g_ref_count_compare             (grefcount       *rc,
      41                                                   gint             val);
      42  
      43  GLIB_AVAILABLE_IN_2_58
      44  void            g_atomic_ref_count_init         (gatomicrefcount *arc);
      45  GLIB_AVAILABLE_IN_2_58
      46  void            g_atomic_ref_count_inc          (gatomicrefcount *arc);
      47  GLIB_AVAILABLE_IN_2_58
      48  gboolean        g_atomic_ref_count_dec          (gatomicrefcount *arc);
      49  GLIB_AVAILABLE_IN_2_58
      50  gboolean        g_atomic_ref_count_compare      (gatomicrefcount *arc,
      51                                                   gint             val);
      52  
      53  /**
      54   * G_REF_COUNT_INIT:
      55   *
      56   * Evaluates to the initial reference count for `grefcount`.
      57   *
      58   * This macro is useful for initializing `grefcount` fields inside
      59   * structures, for instance:
      60   *
      61   * |[<!-- language="C" -->
      62   * typedef struct {
      63   *   grefcount ref_count;
      64   *   char *name;
      65   *   char *address;
      66   * } Person;
      67   *
      68   * static const Person default_person = {
      69   *   .ref_count = G_REF_COUNT_INIT,
      70   *   .name = "Default name",
      71   *   .address = "Default address",
      72   * };
      73   * ]|
      74   *
      75   * Since: 2.78
      76   */
      77  #define G_REF_COUNT_INIT          -1 \
      78    GLIB_AVAILABLE_MACRO_IN_2_78
      79  
      80  /**
      81   * G_ATOMIC_REF_COUNT_INIT:
      82   *
      83   * Evaluates to the initial reference count for `gatomicrefcount`.
      84   *
      85   * This macro is useful for initializing `gatomicrefcount` fields inside
      86   * structures, for instance:
      87   *
      88   * |[<!-- language="C" -->
      89   * typedef struct {
      90   *   gatomicrefcount ref_count;
      91   *   char *name;
      92   *   char *address;
      93   * } Person;
      94   *
      95   * static const Person default_person = {
      96   *   .ref_count = G_ATOMIC_REF_COUNT_INIT,
      97   *   .name = "Default name",
      98   *   .address = "Default address",
      99   * };
     100   * ]|
     101   *
     102   * Since: 2.78
     103   */
     104  #define G_ATOMIC_REF_COUNT_INIT   1 \
     105    GLIB_AVAILABLE_MACRO_IN_2_78
     106  
     107  /* On GCC we can use __extension__ to inline the API without using
     108   * ancillary functions; we only do this when disabling checks, as
     109   * it disables warnings when saturating the reference counters
     110   */
     111  #if defined(__GNUC__) && defined(G_DISABLE_CHECKS)
     112  
     113  # define g_ref_count_init(rc) \
     114    (G_GNUC_EXTENSION ({ \
     115      G_STATIC_ASSERT (sizeof *(rc) == sizeof (grefcount)); \
     116      (void) (0 ? *(rc) ^ *(rc) : 1); \
     117      *(rc) = -1; \
     118    }))
     119  
     120  # define g_ref_count_inc(rc) \
     121    (G_GNUC_EXTENSION ({ \
     122      G_STATIC_ASSERT (sizeof *(rc) == sizeof (grefcount)); \
     123      (void) (0 ? *(rc) ^ *(rc) : 1); \
     124      if (*(rc) == G_MININT) ; else { \
     125        *(rc) -= 1; \
     126      } \
     127    }))
     128  
     129  # define g_ref_count_dec(rc) \
     130    (G_GNUC_EXTENSION ({ \
     131      G_STATIC_ASSERT (sizeof *(rc) == sizeof (grefcount)); \
     132      grefcount __rc = *(rc); \
     133      __rc += 1; \
     134      if (__rc == 0) ; else { \
     135        *(rc) = __rc; \
     136      } \
     137      (gboolean) (__rc == 0); \
     138    }))
     139  
     140  # define g_ref_count_compare(rc,val) \
     141    (G_GNUC_EXTENSION ({ \
     142      G_STATIC_ASSERT (sizeof *(rc) == sizeof (grefcount)); \
     143      (void) (0 ? *(rc) ^ (val) : 1); \
     144      (gboolean) (*(rc) == -(val)); \
     145    }))
     146  
     147  # define g_atomic_ref_count_init(rc) \
     148    (G_GNUC_EXTENSION ({ \
     149      G_STATIC_ASSERT (sizeof *(rc) == sizeof (gatomicrefcount)); \
     150      (void) (0 ? *(rc) ^ *(rc) : 1); \
     151      *(rc) = 1; \
     152    }))
     153  
     154  # define g_atomic_ref_count_inc(rc) \
     155    (G_GNUC_EXTENSION ({ \
     156      G_STATIC_ASSERT (sizeof *(rc) == sizeof (gatomicrefcount)); \
     157      (void) (0 ? *(rc) ^ *(rc) : 1); \
     158      (void) (g_atomic_int_get (rc) == G_MAXINT ? 0 : g_atomic_int_inc ((rc))); \
     159    }))
     160  
     161  # define g_atomic_ref_count_dec(rc) \
     162    (G_GNUC_EXTENSION ({ \
     163      G_STATIC_ASSERT (sizeof *(rc) == sizeof (gatomicrefcount)); \
     164      (void) (0 ? *(rc) ^ *(rc) : 1); \
     165      g_atomic_int_dec_and_test ((rc)); \
     166    }))
     167  
     168  # define g_atomic_ref_count_compare(rc,val) \
     169    (G_GNUC_EXTENSION ({ \
     170      G_STATIC_ASSERT (sizeof *(rc) == sizeof (gatomicrefcount)); \
     171      (void) (0 ? *(rc) ^ (val) : 1); \
     172      (gboolean) (g_atomic_int_get (rc) == (val)); \
     173    }))
     174  
     175  #endif /* __GNUC__ && G_DISABLE_CHECKS */
     176  
     177  G_END_DECLS
     178  
     179  #endif /* __GREFCOUNT_H__ */