diff options
author | Lucas de Castro Borges <lucas@gnuabordo.com.br> | 2024-04-22 00:35:53 -0300 |
---|---|---|
committer | Lucas de Castro Borges <lucas@gnuabordo.com.br> | 2024-04-22 00:35:53 -0300 |
commit | 5f01c706267c595de92406a32e7f31ef5056c2d0 (patch) | |
tree | d1e74ef54efc41ada622900fe3e2a50dee44a237 /deps/uber-graph/g-ring.c | |
parent | 09fcc751ef158898c315ebc9299a0fa3a722d914 (diff) |
New upstream version 2.0.3preupstream/2.0.3pre
Diffstat (limited to 'deps/uber-graph/g-ring.c')
-rw-r--r-- | deps/uber-graph/g-ring.c | 227 |
1 files changed, 227 insertions, 0 deletions
diff --git a/deps/uber-graph/g-ring.c b/deps/uber-graph/g-ring.c new file mode 100644 index 00000000..b014bf74 --- /dev/null +++ b/deps/uber-graph/g-ring.c @@ -0,0 +1,227 @@ +/* g-ring.c + * + * Copyright (C) 2010 Christian Hergert <chris@dronelabs.com> + * + * This file is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This file is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <string.h> + +#include "g-ring.h" + +#ifndef g_malloc0_n +#define g_malloc0_n(x,y) g_malloc0((gsize)x * y) +#endif + +#define get_element(r,i) ((r)->data + ((r)->elt_size * i)) + +typedef struct _GRingImpl GRingImpl; + +struct _GRingImpl +{ + guint8 *data; /* Pointer to real data. */ + guint len; /* Length of data allocation. */ + guint pos; /* Position in ring. */ + guint elt_size; /* Size of each element. */ + gboolean looped; /* Have we wrapped around at least once. */ + GDestroyNotify destroy; /* Destroy element callback. */ + volatile gint ref_count; /* Reference count. */ +}; + +/** + * g_ring_sized_new: + * @element_size: (in): The size per element. + * @reserved_size: (in): The number of elements to allocate. + * @element_destroy: (in): Notification called when removing an element. + * + * Creates a new instance of #GRing with the given number of elements. + * + * Returns: A new #GRing. + * Side effects: None. + */ +GRing* +g_ring_sized_new (guint element_size, + guint reserved_size, + GDestroyNotify element_destroy) +{ + GRingImpl *ring_impl; + + ring_impl = g_slice_new0(GRingImpl); + ring_impl->elt_size = element_size; + ring_impl->len = reserved_size; + ring_impl->data = g_malloc0_n(reserved_size, element_size); + ring_impl->destroy = element_destroy; + ring_impl->ref_count = 1; + + return (GRing *)ring_impl; +} + +/** + * g_ring_append_vals: + * @ring: (in): A #GRing. + * @data: (in): A pointer to the array of values. + * @len: (in): The number of values. + * + * Appends @len values located at @data. + * + * Returns: None. + * Side effects: None. + */ +void +g_ring_append_vals (GRing *ring, + gconstpointer data, + guint len) +{ + GRingImpl *ring_impl = (GRingImpl *)ring; + gpointer idx; + gint x; + guint i; + + g_return_if_fail(ring_impl != NULL); + + for (i = 0; i < len; i++) { + x = (int)ring->pos - i; + if (x < 0) x += ring->len; + idx = ring->data + (ring_impl->elt_size * x); + if (ring_impl->destroy && ring_impl->looped == TRUE) { + ring_impl->destroy(idx); + } + memcpy(idx, data, ring_impl->elt_size); + ring->pos++; + if (ring->pos >= ring->len) { + ring_impl->looped = TRUE; + } + ring->pos %= ring->len; + data += ring_impl->elt_size; + } +} + +/** + * g_ring_foreach: + * @ring: (in): A #GRing. + * @func: (in): A #GFunc to call for each element. + * @user_data: (in): user data for @func. + * + * Calls @func for every item in the #GRing starting from the most recently + * inserted element to the least recently inserted. + * + * Returns: None. + * Side effects: None. + */ +void +g_ring_foreach (GRing *ring, + GFunc func, + gpointer user_data) +{ + GRingImpl *ring_impl = (GRingImpl *)ring; + gint i; + + g_return_if_fail(ring_impl != NULL); + g_return_if_fail(func != NULL); + + for (i = ring_impl->pos - 1; i >= 0; i--) { + func(get_element(ring_impl, i), user_data); + } + for (i = ring->len - 1; i >= (int)ring_impl->pos; i--) { + func(get_element(ring_impl, i), user_data); + } +} + +/** + * g_ring_destroy: + * @ring: (in): A #GRing. + * + * Cleans up after a #GRing that is no longer in use. + * + * Returns: None. + * Side effects: None. + */ +void +g_ring_destroy (GRing *ring) +{ + GRingImpl *ring_impl = (GRingImpl *)ring; + + g_return_if_fail(ring != NULL); + g_return_if_fail(ring_impl->ref_count == 0); + + g_free(ring_impl->data); + g_slice_free(GRingImpl, ring_impl); +} + +/** + * g_ring_ref: + * @ring: (in): A #GRing. + * + * Atomically increments the reference count of @ring by one. + * + * Returns: The @ring pointer. + * Side effects: None. + */ +GRing* +g_ring_ref (GRing *ring) +{ + GRingImpl *ring_impl = (GRingImpl *)ring; + + g_return_val_if_fail(ring != NULL, NULL); + g_return_val_if_fail(ring_impl->ref_count > 0, NULL); + + g_atomic_int_inc(&ring_impl->ref_count); + return ring; +} + +/** + * g_ring_unref: + * @ring: (in): A #GRing. + * + * Atomically decrements the reference count of @ring by one. When the + * reference count reaches zero, the structure is freed. + * + * Returns: None. + * Side effects: None. + */ +void +g_ring_unref (GRing *ring) +{ + GRingImpl *ring_impl = (GRingImpl *)ring; + + g_return_if_fail(ring != NULL); + g_return_if_fail(ring_impl->ref_count > 0); + + if (g_atomic_int_dec_and_test(&ring_impl->ref_count)) { + g_ring_destroy(ring); + } +} + +/** + * g_ring_get_type: + * + * Retrieves the #GType identifier for #GRing. + * + * Returns: The #GType for #GRing. + * Side effects: The type is registered on first call. + */ +GType +g_ring_get_type (void) +{ + static gsize initialized = FALSE; + static GType type_id = 0; + + if (g_once_init_enter(&initialized)) { + type_id = g_boxed_type_register_static("GRing", + (GBoxedCopyFunc)g_ring_ref, + (GBoxedFreeFunc)g_ring_unref); + g_once_init_leave(&initialized, TRUE); + } + return type_id; +} |