glib/glib/gdatasetprivate.h
Thomas Haller 0c06a4b7a0 glib: add internal g_datalist_id_update_atomic() function
GDataSet is mainly used by GObject. Usually, when we access the private
data there, we already hold another lock around the GObject.

For example, before accessing quark_toggle_refs, we take a
OPTIONAL_BIT_LOCK_TOGGLE_REFS lock. That makes sense, because we anyway
need to protect access to the ToggleRefStack. By holding such an
external mutex around several GData operations, we achieve atomic
updates.

However, there is a (performance) use case to update the qdata
atomically, without such additional lock. The GData already holds a lock
while updating the data. Add a new g_datalist_id_update_atomic()
function, that can invoke a callback while holding that lock.

This will be used by GObject. The benefit is that we can access the
GData atomically, without requiring another mutex around it.

For example, a common pattern is to request some GData entry, and if
it's not yet allocated, to allocate it. This requires to take the GData
bitlock twice. With this API, the callback can allocate the data if no
entry exists yet.
2024-01-31 17:30:28 +01:00

68 lines
2.6 KiB
C

/* GLIB - Library of useful routines for C programming
* gdataset-private.h: Internal macros for accessing dataset values
* Copyright (C) 2005 Red Hat
*
* SPDX-License-Identifier: LGPL-2.1-or-later
*
* This library 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 library 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 Lesser General Public
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
/*
* Modified by the GLib Team and others 1997-2000. See the AUTHORS
* file for a list of people on the GLib Team. See the ChangeLog
* files for a list of changes. These files are distributed with
* GLib at ftp://ftp.gtk.org/pub/gtk/.
*/
#ifndef __G_DATASETPRIVATE_H__
#define __G_DATASETPRIVATE_H__
#include <gatomic.h>
G_BEGIN_DECLS
/* GET_FLAGS is implemented via atomic pointer access, to allow memory
* barriers to take effect without acquiring the global dataset mutex.
*/
#define G_DATALIST_GET_FLAGS(datalist) \
((gsize) g_atomic_pointer_get (datalist) & G_DATALIST_FLAGS_MASK)
/*< private >
* GDataListUpdateAtomicFunc:
* @key_id: ID of the entry to update
* @data: (inout) (nullable) (not optional): the existing data corresponding
* to @key_id, and return location for the new value for it
* @destroy_notify: (inout) (nullable) (not optional): the existing destroy
* notify function for @data, and return location for the destroy notify
* function for the new value for it
* @user_data: user data passed in to [func@GLib.datalist_id_update_atomic]
*
* Callback from [func@GLib.datalist_id_update_atomic].
*
* Since: 2.80
*/
typedef gpointer (*GDataListUpdateAtomicFunc) (GQuark key_id,
gpointer *data,
GDestroyNotify *destroy_notify,
gpointer user_data);
gpointer g_datalist_id_update_atomic (GData **datalist,
GQuark key_id,
GDataListUpdateAtomicFunc callback,
gpointer user_data);
G_END_DECLS
#endif /* __G_DATASETPRIVATE_H__ */