mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-01-12 15:36:17 +01:00
Merge branch 'migrate-to-gi-docgen12' into 'main'
gdir, gstrvbuilder: Add refcounting support and a boxed type See merge request GNOME/glib!3722
This commit is contained in:
commit
e4fe837bae
100
glib/gdir.c
100
glib/gdir.c
@ -56,6 +56,7 @@
|
|||||||
|
|
||||||
struct _GDir
|
struct _GDir
|
||||||
{
|
{
|
||||||
|
gatomicrefcount ref_count;
|
||||||
#ifdef G_OS_WIN32
|
#ifdef G_OS_WIN32
|
||||||
_WDIR *wdirp;
|
_WDIR *wdirp;
|
||||||
#else
|
#else
|
||||||
@ -89,10 +90,13 @@ GDir *
|
|||||||
g_dir_open_with_errno (const gchar *path,
|
g_dir_open_with_errno (const gchar *path,
|
||||||
guint flags)
|
guint flags)
|
||||||
{
|
{
|
||||||
GDir dir;
|
|
||||||
#ifdef G_OS_WIN32
|
#ifdef G_OS_WIN32
|
||||||
|
GDir *dir;
|
||||||
|
_WDIR *wdirp;
|
||||||
gint saved_errno;
|
gint saved_errno;
|
||||||
wchar_t *wpath;
|
wchar_t *wpath;
|
||||||
|
#else
|
||||||
|
DIR *dirp;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
g_return_val_if_fail (path != NULL, NULL);
|
g_return_val_if_fail (path != NULL, NULL);
|
||||||
@ -102,21 +106,27 @@ g_dir_open_with_errno (const gchar *path,
|
|||||||
|
|
||||||
g_return_val_if_fail (wpath != NULL, NULL);
|
g_return_val_if_fail (wpath != NULL, NULL);
|
||||||
|
|
||||||
dir.wdirp = _wopendir (wpath);
|
wdirp = _wopendir (wpath);
|
||||||
saved_errno = errno;
|
saved_errno = errno;
|
||||||
g_free (wpath);
|
g_free (wpath);
|
||||||
errno = saved_errno;
|
errno = saved_errno;
|
||||||
|
|
||||||
if (dir.wdirp == NULL)
|
if (wdirp == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
dir = g_new0 (GDir, 1);
|
||||||
|
g_atomic_ref_count_init (&dir->ref_count);
|
||||||
|
dir->wdirp = wdirp;
|
||||||
|
|
||||||
|
return g_steal_pointer (&dir);
|
||||||
#else
|
#else
|
||||||
dir.dirp = opendir (path);
|
dirp = opendir (path);
|
||||||
|
|
||||||
if (dir.dirp == NULL)
|
if (dirp == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
#endif
|
|
||||||
|
|
||||||
return g_memdup2 (&dir, sizeof dir);
|
return g_dir_new_from_dirp (dirp);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -187,7 +197,8 @@ g_dir_new_from_dirp (gpointer dirp)
|
|||||||
|
|
||||||
g_return_val_if_fail (dirp != NULL, NULL);
|
g_return_val_if_fail (dirp != NULL, NULL);
|
||||||
|
|
||||||
dir = g_new (GDir, 1);
|
dir = g_new0 (GDir, 1);
|
||||||
|
g_atomic_ref_count_init (&dir->ref_count);
|
||||||
dir->dirp = dirp;
|
dir->dirp = dirp;
|
||||||
|
|
||||||
return dir;
|
return dir;
|
||||||
@ -287,24 +298,85 @@ g_dir_rewind (GDir *dir)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
g_dir_actually_close (GDir *dir)
|
||||||
|
{
|
||||||
|
#ifdef G_OS_WIN32
|
||||||
|
g_clear_pointer (&dir->wdirp, _wclosedir);
|
||||||
|
#else
|
||||||
|
g_clear_pointer (&dir->dirp, closedir);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* g_dir_close:
|
* g_dir_close:
|
||||||
* @dir: (transfer full): a #GDir* created by g_dir_open()
|
* @dir: (transfer full): a #GDir* created by g_dir_open()
|
||||||
*
|
*
|
||||||
* Closes the directory and deallocates all related resources.
|
* Closes the directory immediately and decrements the reference count.
|
||||||
|
*
|
||||||
|
* Once the reference count reaches zero, the `GDir` structure itself will be
|
||||||
|
* freed. Prior to GLib 2.80, `GDir` was not reference counted.
|
||||||
|
*
|
||||||
|
* It is an error to call any of the `GDir` methods other than
|
||||||
|
* [method@GLib.Dir.ref] and [method@GLib.Dir.unref] on a `GDir` after calling
|
||||||
|
* [method@GLib.Dir.close] on it.
|
||||||
**/
|
**/
|
||||||
void
|
void
|
||||||
g_dir_close (GDir *dir)
|
g_dir_close (GDir *dir)
|
||||||
{
|
{
|
||||||
g_return_if_fail (dir != NULL);
|
g_return_if_fail (dir != NULL);
|
||||||
|
|
||||||
#ifdef G_OS_WIN32
|
g_dir_actually_close (dir);
|
||||||
_wclosedir (dir->wdirp);
|
g_dir_unref (dir);
|
||||||
#else
|
}
|
||||||
closedir (dir->dirp);
|
|
||||||
#endif
|
/**
|
||||||
|
* g_dir_ref:
|
||||||
|
* @dir: (transfer none): a `GDir`
|
||||||
|
*
|
||||||
|
* Increment the reference count of `dir`.
|
||||||
|
*
|
||||||
|
* Returns: (transfer full): the same pointer as `dir`
|
||||||
|
* Since: 2.80
|
||||||
|
*/
|
||||||
|
GDir *
|
||||||
|
g_dir_ref (GDir *dir)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (dir != NULL, NULL);
|
||||||
|
|
||||||
|
g_atomic_ref_count_inc (&dir->ref_count);
|
||||||
|
return dir;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* g_dir_unref:
|
||||||
|
* @dir: (transfer full): a `GDir`
|
||||||
|
*
|
||||||
|
* Decrements the reference count of `dir`.
|
||||||
|
*
|
||||||
|
* Once the reference count reaches zero, the directory will be closed and all
|
||||||
|
* resources associated with it will be freed. If [method@GLib.Dir.close] is
|
||||||
|
* called when the reference count is greater than zero, the directory is closed
|
||||||
|
* but the `GDir` structure will not be freed until its reference count reaches
|
||||||
|
* zero.
|
||||||
|
*
|
||||||
|
* It is an error to call any of the `GDir` methods other than
|
||||||
|
* [method@GLib.Dir.ref] and [method@GLib.Dir.unref] on a `GDir` after calling
|
||||||
|
* [method@GLib.Dir.close] on it.
|
||||||
|
*
|
||||||
|
* Since: 2.80
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
g_dir_unref (GDir *dir)
|
||||||
|
{
|
||||||
|
g_return_if_fail (dir != NULL);
|
||||||
|
|
||||||
|
if (g_atomic_ref_count_dec (&dir->ref_count))
|
||||||
|
{
|
||||||
|
g_dir_actually_close (dir);
|
||||||
g_free (dir);
|
g_free (dir);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef G_OS_WIN32
|
#ifdef G_OS_WIN32
|
||||||
|
|
||||||
|
@ -49,6 +49,11 @@ void g_dir_rewind (GDir *dir);
|
|||||||
GLIB_AVAILABLE_IN_ALL
|
GLIB_AVAILABLE_IN_ALL
|
||||||
void g_dir_close (GDir *dir);
|
void g_dir_close (GDir *dir);
|
||||||
|
|
||||||
|
GLIB_AVAILABLE_IN_2_80
|
||||||
|
GDir * g_dir_ref (GDir *dir);
|
||||||
|
GLIB_AVAILABLE_IN_2_80
|
||||||
|
void g_dir_unref (GDir *dir);
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|
||||||
#endif /* __G_DIR_H__ */
|
#endif /* __G_DIR_H__ */
|
||||||
|
@ -57,7 +57,7 @@ typedef struct stat GStatBuf;
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(G_OS_UNIX) && !defined(G_STDIO_WRAP_ON_UNIX)
|
#if defined(G_OS_UNIX) && !defined(G_STDIO_WRAP_ON_UNIX) && !defined(__GI_SCANNER__)
|
||||||
|
|
||||||
/* Just pass on to the system functions, so there's no potential for data
|
/* Just pass on to the system functions, so there's no potential for data
|
||||||
* format mismatches, especially with large file interfaces.
|
* format mismatches, especially with large file interfaces.
|
||||||
|
@ -41,6 +41,29 @@ test_dir_nonexisting (void)
|
|||||||
g_error_free (error);
|
g_error_free (error);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_dir_refcounting (void)
|
||||||
|
{
|
||||||
|
GDir *dir;
|
||||||
|
GError *local_error = NULL;
|
||||||
|
|
||||||
|
g_test_summary ("Test refcounting interactions with g_dir_close()");
|
||||||
|
|
||||||
|
/* Try keeping the `GDir` struct alive after closing it. */
|
||||||
|
dir = g_dir_open (".", 0, &local_error);
|
||||||
|
g_assert_no_error (local_error);
|
||||||
|
|
||||||
|
g_dir_ref (dir);
|
||||||
|
g_dir_close (dir);
|
||||||
|
g_dir_unref (dir);
|
||||||
|
|
||||||
|
/* Test that dropping the last ref closes it. Any leak here should be caught
|
||||||
|
* when the test is run under valgrind. */
|
||||||
|
dir = g_dir_open (".", 0, &local_error);
|
||||||
|
g_assert_no_error (local_error);
|
||||||
|
g_dir_unref (dir);
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
main (int argc, char *argv[])
|
main (int argc, char *argv[])
|
||||||
{
|
{
|
||||||
@ -48,6 +71,7 @@ main (int argc, char *argv[])
|
|||||||
|
|
||||||
g_test_add_func ("/dir/read", test_dir_read);
|
g_test_add_func ("/dir/read", test_dir_read);
|
||||||
g_test_add_func ("/dir/nonexisting", test_dir_nonexisting);
|
g_test_add_func ("/dir/nonexisting", test_dir_nonexisting);
|
||||||
|
g_test_add_func ("/dir/refcounting", test_dir_refcounting);
|
||||||
|
|
||||||
return g_test_run ();
|
return g_test_run ();
|
||||||
}
|
}
|
||||||
|
@ -139,6 +139,7 @@ G_DEFINE_BOXED_TYPE (GKeyFile, g_key_file, g_key_file_ref, g_key_file_unref)
|
|||||||
G_DEFINE_BOXED_TYPE (GMappedFile, g_mapped_file, g_mapped_file_ref, g_mapped_file_unref)
|
G_DEFINE_BOXED_TYPE (GMappedFile, g_mapped_file, g_mapped_file_ref, g_mapped_file_unref)
|
||||||
G_DEFINE_BOXED_TYPE (GBookmarkFile, g_bookmark_file, g_bookmark_file_copy, g_bookmark_file_free)
|
G_DEFINE_BOXED_TYPE (GBookmarkFile, g_bookmark_file, g_bookmark_file_copy, g_bookmark_file_free)
|
||||||
G_DEFINE_BOXED_TYPE (GHmac, g_hmac, g_hmac_ref, g_hmac_unref)
|
G_DEFINE_BOXED_TYPE (GHmac, g_hmac, g_hmac_ref, g_hmac_unref)
|
||||||
|
G_DEFINE_BOXED_TYPE (GDir, g_dir, g_dir_ref, g_dir_unref)
|
||||||
|
|
||||||
G_DEFINE_BOXED_TYPE (GMainLoop, g_main_loop, g_main_loop_ref, g_main_loop_unref)
|
G_DEFINE_BOXED_TYPE (GMainLoop, g_main_loop, g_main_loop_ref, g_main_loop_unref)
|
||||||
G_DEFINE_BOXED_TYPE (GMainContext, g_main_context, g_main_context_ref, g_main_context_unref)
|
G_DEFINE_BOXED_TYPE (GMainContext, g_main_context, g_main_context_ref, g_main_context_unref)
|
||||||
@ -153,6 +154,8 @@ G_DEFINE_BOXED_TYPE (GUri, g_uri, g_uri_ref, g_uri_unref)
|
|||||||
G_DEFINE_BOXED_TYPE (GOptionGroup, g_option_group, g_option_group_ref, g_option_group_unref)
|
G_DEFINE_BOXED_TYPE (GOptionGroup, g_option_group, g_option_group_ref, g_option_group_unref)
|
||||||
G_DEFINE_BOXED_TYPE (GPatternSpec, g_pattern_spec, g_pattern_spec_copy, g_pattern_spec_free);
|
G_DEFINE_BOXED_TYPE (GPatternSpec, g_pattern_spec, g_pattern_spec_copy, g_pattern_spec_free);
|
||||||
|
|
||||||
|
G_DEFINE_BOXED_TYPE (GStrvBuilder, g_strv_builder, g_strv_builder_ref, g_strv_builder_unref);
|
||||||
|
|
||||||
/* This one can't use G_DEFINE_BOXED_TYPE (GStrv, g_strv, g_strdupv, g_strfreev) */
|
/* This one can't use G_DEFINE_BOXED_TYPE (GStrv, g_strv, g_strdupv, g_strfreev) */
|
||||||
GType
|
GType
|
||||||
g_strv_get_type (void)
|
g_strv_get_type (void)
|
||||||
|
@ -345,6 +345,24 @@ typedef gsize GType;
|
|||||||
*/
|
*/
|
||||||
#define G_TYPE_HMAC (g_hmac_get_type ())
|
#define G_TYPE_HMAC (g_hmac_get_type ())
|
||||||
|
|
||||||
|
/**
|
||||||
|
* G_TYPE_DIR:
|
||||||
|
*
|
||||||
|
* The #GType for a boxed type holding a #GDir.
|
||||||
|
*
|
||||||
|
* Since: 2.80
|
||||||
|
*/
|
||||||
|
#define G_TYPE_DIR (g_dir_get_type ())
|
||||||
|
|
||||||
|
/**
|
||||||
|
* G_TYPE_STRV_BUILDER:
|
||||||
|
*
|
||||||
|
* The #GType for a boxed type holding a #GStrvBuilder.
|
||||||
|
*
|
||||||
|
* Since: 2.80
|
||||||
|
*/
|
||||||
|
#define G_TYPE_STRV_BUILDER (g_strv_builder_get_type ())
|
||||||
|
|
||||||
GOBJECT_AVAILABLE_IN_ALL
|
GOBJECT_AVAILABLE_IN_ALL
|
||||||
GType g_date_get_type (void) G_GNUC_CONST;
|
GType g_date_get_type (void) G_GNUC_CONST;
|
||||||
GOBJECT_AVAILABLE_IN_ALL
|
GOBJECT_AVAILABLE_IN_ALL
|
||||||
@ -411,6 +429,10 @@ GOBJECT_AVAILABLE_IN_2_76
|
|||||||
GType g_bookmark_file_get_type (void) G_GNUC_CONST;
|
GType g_bookmark_file_get_type (void) G_GNUC_CONST;
|
||||||
GOBJECT_AVAILABLE_IN_2_80
|
GOBJECT_AVAILABLE_IN_2_80
|
||||||
GType g_hmac_get_type (void) G_GNUC_CONST;
|
GType g_hmac_get_type (void) G_GNUC_CONST;
|
||||||
|
GOBJECT_AVAILABLE_IN_2_80
|
||||||
|
GType g_dir_get_type (void) G_GNUC_CONST;
|
||||||
|
GOBJECT_AVAILABLE_IN_2_80
|
||||||
|
GType g_strv_builder_get_type (void) G_GNUC_CONST;
|
||||||
|
|
||||||
GOBJECT_DEPRECATED_FOR('G_TYPE_VARIANT')
|
GOBJECT_DEPRECATED_FOR('G_TYPE_VARIANT')
|
||||||
GType g_variant_get_gtype (void) G_GNUC_CONST;
|
GType g_variant_get_gtype (void) G_GNUC_CONST;
|
||||||
|
Loading…
Reference in New Issue
Block a user