From ee79356371048f5a9e3b094da034adb620f9273f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20Denis-Courmont?= Date: Tue, 20 Feb 2018 21:30:11 +0200 Subject: [PATCH] compat: add tdestroy() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This adds a thread-safe tdestroy() replacement for systems without it but with tfind(). This should fix linking failures on BSD. (cherry picked from commit 320938b4bf527712a73b00fcb05da2bd9457a6a4) Signed-off-by: Rémi Denis-Courmont --- compat/tdestroy.c | 100 +++++++++++++++++++++++++++++++++++++++++++ configure.ac | 2 +- include/vlc_fixups.h | 7 ++- 3 files changed, 104 insertions(+), 5 deletions(-) create mode 100644 compat/tdestroy.c diff --git a/compat/tdestroy.c b/compat/tdestroy.c new file mode 100644 index 0000000000..6bb3480957 --- /dev/null +++ b/compat/tdestroy.c @@ -0,0 +1,100 @@ +/** + * @file tdestroy.c + * @brief replacement for GNU tdestroy() + */ +/***************************************************************************** + * Copyright (C) 2009, 2018 Rémi Denis-Courmont + * + * This program 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 program 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 program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. + *****************************************************************************/ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include +#ifdef HAVE_SEARCH_H +# include +#endif + +#ifdef HAVE_TFIND +static __thread struct +{ + const void **tab; + size_t count; +} list = { NULL, 0 }; + +static void list_nodes(const void *node, const VISIT which, const int depth) +{ + (void) depth; + + if (which != postorder && which != leaf) + return; + + const void **tab = realloc(list.tab, sizeof (*tab) * (list.count + 1)); + if (tab == NULL) + abort(); + + tab[list.count] = *(const void **)node; + list.tab = tab; + list.count++; +} + +static __thread const void *smallest; + +static int cmp_smallest(const void *a, const void *b) +{ + if (a == b) + return 0; + if (a == smallest) + return -1; + if (b == smallest) + return +1; + abort(); +} + +void tdestroy(void *root, void (*freenode)(void *)) +{ + const void **tab; + size_t count; + + assert(freenode != NULL); + + /* Enumerate nodes in order */ + assert(list.count == 0); + twalk(root, list_nodes); + tab = list.tab; + count = list.count; + list.tab = NULL; + list.count = 0; + + /* Destroy the tree */ + for (size_t i = 0; i < count; i++) + { + void *node = (void *)(tab[i]); + + smallest = node; + node = tdelete(node, &root, cmp_smallest); + assert(node != NULL); + } + assert (root == NULL); + + /* Destroy the nodes */ + for (size_t i = 0; i < count; i++) + freenode((void *)(tab[i])); + free(tab); +} +#endif /* HAVE_TFIND */ diff --git a/configure.ac b/configure.ac index c5d7a41063..973335e57b 100644 --- a/configure.ac +++ b/configure.ac @@ -591,7 +591,7 @@ need_libc=false dnl Check for usual libc functions AC_CHECK_FUNCS([accept4 daemon fcntl flock fstatvfs fork getenv getpwuid_r isatty lstat memalign mkostemp mmap open_memstream openat pipe2 pread posix_fadvise posix_madvise posix_memalign setlocale stricmp strnicmp strptime tdestroy uselocale]) -AC_REPLACE_FUNCS([aligned_alloc atof atoll dirfd fdopendir ffsll flockfile fsync getdelim getpid lldiv memrchr nrand48 poll recvmsg rewind sendmsg setenv strcasecmp strcasestr strdup strlcpy strndup strnlen strnstr strsep strtof strtok_r strtoll swab tfind timegm timespec_get strverscmp pathconf]) +AC_REPLACE_FUNCS([aligned_alloc atof atoll dirfd fdopendir ffsll flockfile fsync getdelim getpid lldiv memrchr nrand48 poll recvmsg rewind sendmsg setenv strcasecmp strcasestr strdup strlcpy strndup strnlen strnstr strsep strtof strtok_r strtoll swab tdestroy tfind timegm timespec_get strverscmp pathconf]) AC_REPLACE_FUNCS([gettimeofday]) AC_CHECK_FUNC(fdatasync,, [AC_DEFINE(fdatasync, fsync, [Alias fdatasync() to fsync() if missing.]) diff --git a/include/vlc_fixups.h b/include/vlc_fixups.h index d6ad945f01..e48e7a05bd 100644 --- a/include/vlc_fixups.h +++ b/include/vlc_fixups.h @@ -480,12 +480,11 @@ void *tsearch( const void *key, void **rootp, int(*cmp)(const void *, const void void *tfind( const void *key, const void **rootp, int(*cmp)(const void *, const void *) ); void *tdelete( const void *key, void **rootp, int(*cmp)(const void *, const void *) ); void twalk( const void *root, void(*action)(const void *nodep, VISIT which, int depth) ); +#endif /* HAVE_SEARCH_H */ +#ifndef HAVE_TDESTROY void tdestroy( void *root, void (*free_node)(void *nodep) ); -#else // HAVE_SEARCH_H -# ifndef HAVE_TDESTROY void vlc_tdestroy( void *, void (*)(void *) ); -# define tdestroy vlc_tdestroy -# endif +# define tdestroy vlc_tdestroy #endif /* Random numbers */