]> git.sesse.net Git - vlc/blob - src/extras/tdestroy.c
Use var_Inherit* instead of var_CreateGet*.
[vlc] / src / extras / tdestroy.c
1 /**
2  * @file tdestroy.c
3  * @brief replacement for GNU tdestroy()
4  */
5 /*****************************************************************************
6  * Copyright (C) 2009 RĂ©mi Denis-Courmont
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU Lesser General Public License as published by
10  * the Free Software Foundation; either version 2.1 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
21  *****************************************************************************/
22
23 #ifdef HAVE_CONFIG_H
24 # include "config.h"
25 #endif
26
27 #include <stdlib.h>
28 #include <assert.h>
29
30 #include <vlc_common.h>
31
32 #ifdef HAVE_TDESTROY
33 void vlc_tdestroy (void *root, void (*freenode) (void *))
34 {
35     (void) root;
36     assert (freenode != NULL);
37     abort ();
38 }
39
40 #else
41 #include <search.h>
42
43 static struct
44 {
45     const void **tab;
46     size_t count;
47     vlc_mutex_t lock;
48 } list = { NULL, 0, VLC_STATIC_MUTEX };
49
50 static void list_nodes (const void *node, const VISIT which, const int depth)
51 {
52     (void) depth;
53
54     if (which != postorder && which != leaf)
55         return;
56
57     const void **tab = realloc (list.tab, sizeof (*tab) * (list.count + 1));
58     if (unlikely(tab == NULL))
59         abort ();
60
61     tab[list.count] = *(const void **)node;
62     list.tab = tab;
63     list.count++;
64 }
65
66 static struct
67 {
68     const void *node;
69     vlc_mutex_t lock;
70 } smallest = { NULL, VLC_STATIC_MUTEX };
71
72 static int cmp_smallest (const void *a, const void *b)
73 {
74     if (a == b)
75         return 0;
76     if (a == smallest.node)
77         return -1;
78     if (likely(b == smallest.node))
79         return +1;
80     abort ();
81 }
82
83 void vlc_tdestroy (void *root, void (*freenode) (void *))
84 {
85     const void **tab;
86     size_t count;
87
88     assert (freenode != NULL);
89
90     /* Enumerate nodes in order */
91     vlc_mutex_lock (&list.lock);
92     assert (list.count == 0);
93     twalk (root, list_nodes);
94     tab = list.tab;
95     count = list.count;
96     list.tab = NULL;
97     list.count = 0;
98     vlc_mutex_unlock (&list.lock);
99
100     /* Destroy the tree */
101     vlc_mutex_lock (&smallest.lock);
102     for (size_t i = 0; i < count; i++)
103     {
104          smallest.node = tab[i];
105          if (tdelete (smallest.node, &root, cmp_smallest) == NULL)
106              abort ();
107     }
108     vlc_mutex_unlock (&smallest.lock);
109     assert (root == NULL);
110
111     /* Destroy the nodes */
112     for (size_t i = 0; i < count; i++)
113          freenode ((void *)(tab[i]));
114     free (tab);
115 }
116
117 #endif