2 * collectd - src/utils_heap.c
3 * Copyright (C) 2009 Florian octo Forster
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2 of the License, or (at your
8 * option) any later version.
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20 * Florian octo Forster <octo at verplant.org>
29 #include "utils_heap.h"
34 int (*compare) (const void *, const void *);
37 size_t list_len; /* # entries used */
38 size_t list_size; /* # entries allocated */
47 static void reheap (c_heap_t *h, size_t root, enum reheap_direction dir)
54 /* Calculate the positions of the children */
55 left = (2 * root) + 1;
56 if (left >= h->list_len)
59 right = (2 * root) + 2;
60 if (right >= h->list_len)
63 /* Check which one of the children is smaller. */
64 if ((left == 0) && (right == 0))
72 status = h->compare (h->list[left], h->list[right]);
79 status = h->compare (h->list[root], h->list[min]);
82 /* We didn't need to change anything, so the rest of the tree should be
86 else /* if (status > 0) */
91 h->list[root] = h->list[min];
95 if ((dir == DIR_UP) && (root == 0))
99 reheap (h, (root - 1) / 2, dir);
100 else if (dir == DIR_DOWN)
101 reheap (h, min, dir);
104 c_heap_t *c_heap_create (int (*compare) (const void *, const void *))
111 h = malloc (sizeof (*h));
115 memset (h, 0, sizeof (*h));
116 pthread_mutex_init (&h->lock, /* attr = */ NULL);
117 h->compare = compare;
124 } /* c_heap_t *c_heap_create */
126 void c_heap_destroy (c_heap_t *h)
136 pthread_mutex_destroy (&h->lock);
139 } /* void c_heap_destroy */
141 int c_heap_insert (c_heap_t *h, void *ptr)
145 if ((h == NULL) || (ptr == NULL))
148 pthread_mutex_lock (&h->lock);
150 assert (h->list_len <= h->list_size);
151 if (h->list_len == h->list_size)
155 tmp = realloc (h->list, (h->list_size + 16) * sizeof (*h->list));
158 pthread_mutex_unlock (&h->lock);
166 /* Insert the new node as a leaf. */
168 h->list[index] = ptr;
171 /* Reorganize the heap from bottom up. */
172 reheap (h, /* parent of this node = */ (index - 1) / 2, DIR_UP);
174 pthread_mutex_unlock (&h->lock);
176 } /* int c_heap_insert */
178 void *c_heap_get_root (c_heap_t *h)
185 pthread_mutex_lock (&h->lock);
187 if (h->list_len == 0)
189 pthread_mutex_unlock (&h->lock);
192 else if (h->list_len == 1)
198 else /* if (h->list_len > 1) */
201 h->list[0] = h->list[h->list_len - 1];
202 h->list[h->list_len - 1] = NULL;
205 reheap (h, /* root = */ 0, DIR_DOWN);
208 /* free some memory */
209 if ((h->list_len + 32) < h->list_size)
213 tmp = realloc (h->list, (h->list_len + 16) * sizeof (*h->list));
217 h->list_size = h->list_len + 16;
221 pthread_mutex_unlock (&h->lock);
224 } /* void *c_heap_get_root */
226 /* vim: set sw=2 sts=2 et fdm=marker : */