(root)/
glib-2.79.0/
glib/
garcbox.c
       1  /* garcbox.c: Atomically reference counted data
       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  #include "config.h"
      22  
      23  #include "grcboxprivate.h"
      24  
      25  #include "gmessages.h"
      26  #include "grefcount.h"
      27  
      28  #ifdef ENABLE_VALGRIND
      29  #include "valgrind.h"
      30  #endif
      31  
      32  #include "glib_trace.h"
      33  
      34  #include <string.h>
      35  
      36  #define G_ARC_BOX(p)            (GArcBox *) (((char *) (p)) - G_ARC_BOX_SIZE)
      37  
      38  /**
      39   * g_atomic_rc_box_alloc:
      40   * @block_size: the size of the allocation, must be greater than 0
      41   *
      42   * Allocates @block_size bytes of memory, and adds atomic
      43   * reference counting semantics to it.
      44   *
      45   * The data will be freed when its reference count drops to
      46   * zero.
      47   *
      48   * The allocated data is guaranteed to be suitably aligned for any
      49   * built-in type.
      50   *
      51   * Returns: (transfer full) (not nullable): a pointer to the allocated memory
      52   *
      53   * Since: 2.58
      54   */
      55  gpointer
      56  g_atomic_rc_box_alloc (gsize block_size)
      57  {
      58    g_return_val_if_fail (block_size > 0, NULL);
      59  
      60    return g_rc_box_alloc_full (block_size, STRUCT_ALIGNMENT, TRUE, FALSE);
      61  }
      62  
      63  /**
      64   * g_atomic_rc_box_alloc0:
      65   * @block_size: the size of the allocation, must be greater than 0
      66   *
      67   * Allocates @block_size bytes of memory, and adds atomic
      68   * reference counting semantics to it.
      69   *
      70   * The contents of the returned data is set to zero.
      71   *
      72   * The data will be freed when its reference count drops to
      73   * zero.
      74   *
      75   * The allocated data is guaranteed to be suitably aligned for any
      76   * built-in type.
      77   *
      78   * Returns: (transfer full) (not nullable): a pointer to the allocated memory
      79   *
      80   * Since: 2.58
      81   */
      82  gpointer
      83  g_atomic_rc_box_alloc0 (gsize block_size)
      84  {
      85    g_return_val_if_fail (block_size > 0, NULL);
      86  
      87    return g_rc_box_alloc_full (block_size, STRUCT_ALIGNMENT, TRUE, TRUE);
      88  }
      89  
      90  /**
      91   * g_atomic_rc_box_new:
      92   * @type: the type to allocate, typically a structure name
      93   *
      94   * A convenience macro to allocate atomically reference counted
      95   * data with the size of the given @type.
      96   *
      97   * This macro calls g_atomic_rc_box_alloc() with `sizeof (@type)` and
      98   * casts the returned pointer to a pointer of the given @type,
      99   * avoiding a type cast in the source code.
     100   *
     101   * Returns: (transfer full) (not nullable): a pointer to the allocated
     102   *   memory, cast to a pointer for the given @type
     103   *
     104   * Since: 2.58
     105   */
     106  
     107  /**
     108   * g_atomic_rc_box_new0:
     109   * @type: the type to allocate, typically a structure name
     110   *
     111   * A convenience macro to allocate atomically reference counted
     112   * data with the size of the given @type, and set its contents
     113   * to zero.
     114   *
     115   * This macro calls g_atomic_rc_box_alloc0() with `sizeof (@type)` and
     116   * casts the returned pointer to a pointer of the given @type,
     117   * avoiding a type cast in the source code.
     118   *
     119   * Returns: (transfer full) (not nullable): a pointer to the allocated
     120   *   memory, cast to a pointer for the given @type
     121   *
     122   * Since: 2.58
     123   */
     124  
     125  /**
     126   * g_atomic_rc_box_dup:
     127   * @block_size: the number of bytes to copy, must be greater than 0
     128   * @mem_block: (not nullable): the memory to copy
     129   *
     130   * Allocates a new block of data with atomic reference counting
     131   * semantics, and copies @block_size bytes of @mem_block
     132   * into it.
     133   *
     134   * Returns: (transfer full) (not nullable): a pointer to the allocated
     135   *   memory
     136   *
     137   * Since: 2.58
     138   */
     139  gpointer
     140  (g_atomic_rc_box_dup) (gsize         block_size,
     141                         gconstpointer mem_block)
     142  {
     143    gpointer res;
     144  
     145    g_return_val_if_fail (block_size > 0, NULL);
     146    g_return_val_if_fail (mem_block != NULL, NULL);
     147  
     148    res = g_rc_box_alloc_full (block_size, STRUCT_ALIGNMENT, TRUE, FALSE);
     149    memcpy (res, mem_block, block_size);
     150  
     151    return res;
     152  }
     153  
     154  /**
     155   * g_atomic_rc_box_acquire:
     156   * @mem_block: (not nullable): a pointer to reference counted data
     157   *
     158   * Atomically acquires a reference on the data pointed by @mem_block.
     159   *
     160   * Returns: (transfer full) (not nullable): a pointer to the data,
     161   *   with its reference count increased
     162   *
     163   * Since: 2.58
     164   */
     165  gpointer
     166  (g_atomic_rc_box_acquire) (gpointer mem_block)
     167  {
     168    GArcBox *real_box = G_ARC_BOX (mem_block);
     169  
     170    g_return_val_if_fail (mem_block != NULL, NULL);
     171  #ifndef G_DISABLE_ASSERT
     172    g_return_val_if_fail (real_box->magic == G_BOX_MAGIC, NULL);
     173  #endif
     174  
     175    g_atomic_ref_count_inc (&real_box->ref_count);
     176  
     177    TRACE (GLIB_RCBOX_ACQUIRE (mem_block, 1));
     178  
     179    return mem_block;
     180  }
     181  
     182  /**
     183   * g_atomic_rc_box_release:
     184   * @mem_block: (transfer full) (not nullable): a pointer to reference counted data
     185   *
     186   * Atomically releases a reference on the data pointed by @mem_block.
     187   *
     188   * If the reference was the last one, it will free the
     189   * resources allocated for @mem_block.
     190   *
     191   * Since: 2.58
     192   */
     193  void
     194  g_atomic_rc_box_release (gpointer mem_block)
     195  {
     196    g_atomic_rc_box_release_full (mem_block, NULL);
     197  }
     198  
     199  /**
     200   * g_atomic_rc_box_release_full:
     201   * @mem_block: (transfer full) (not nullable): a pointer to reference counted data
     202   * @clear_func: (not nullable): a function to call when clearing the data
     203   *
     204   * Atomically releases a reference on the data pointed by @mem_block.
     205   *
     206   * If the reference was the last one, it will call @clear_func
     207   * to clear the contents of @mem_block, and then will free the
     208   * resources allocated for @mem_block.
     209   *
     210   * Since: 2.58
     211   */
     212  void
     213  g_atomic_rc_box_release_full (gpointer       mem_block,
     214                                GDestroyNotify clear_func)
     215  {
     216    GArcBox *real_box = G_ARC_BOX (mem_block);
     217  
     218    g_return_if_fail (mem_block != NULL);
     219  #ifndef G_DISABLE_ASSERT
     220    g_return_if_fail (real_box->magic == G_BOX_MAGIC);
     221  #endif
     222  
     223    if (g_atomic_ref_count_dec (&real_box->ref_count))
     224      {
     225        char *real_mem = (char *) real_box - real_box->private_offset;
     226  
     227        TRACE (GLIB_RCBOX_RELEASE (mem_block, 1));
     228  
     229        if (clear_func != NULL)
     230          clear_func (mem_block);
     231  
     232        TRACE (GLIB_RCBOX_FREE (mem_block));
     233        g_free (real_mem);
     234      }
     235  }
     236  
     237  /**
     238   * g_atomic_rc_box_get_size:
     239   * @mem_block: (not nullable): a pointer to reference counted data
     240   *
     241   * Retrieves the size of the reference counted data pointed by @mem_block.
     242   *
     243   * Returns: the size of the data, in bytes
     244   *
     245   * Since: 2.58
     246   */
     247  gsize
     248  g_atomic_rc_box_get_size (gpointer mem_block)
     249  {
     250    GArcBox *real_box = G_ARC_BOX (mem_block);
     251  
     252    g_return_val_if_fail (mem_block != NULL, 0);
     253  #ifndef G_DISABLE_ASSERT
     254    g_return_val_if_fail (real_box->magic == G_BOX_MAGIC, 0);
     255  #endif
     256  
     257    return real_box->mem_size;
     258  }