/*-1* SPDX-License-Identifier: BSD-2-Clause2*3* Copyright (c) 1998-2010 Luigi Rizzo, Universita` di Pisa4* All rights reserved5*6* Redistribution and use in source and binary forms, with or without7* modification, are permitted provided that the following conditions8* are met:9* 1. Redistributions of source code must retain the above copyright10* notice, this list of conditions and the following disclaimer.11* 2. Redistributions in binary form must reproduce the above copyright12* notice, this list of conditions and the following disclaimer in the13* documentation and/or other materials provided with the distribution.14*15* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND16* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE17* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE18* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE19* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL20* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS21* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)22* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT23* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY24* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF25* SUCH DAMAGE.26*/2728/*29* Binary heap and hash tables, header file30*/3132#ifndef _IP_DN_HEAP_H33#define _IP_DN_HEAP_H3435#define DN_KEY_LT(a,b) ((int64_t)((a)-(b)) < 0)36#define DN_KEY_LEQ(a,b) ((int64_t)((a)-(b)) <= 0)3738/*39* This module implements a binary heap supporting random extraction.40*41* A heap entry contains an uint64_t key and a pointer to object.42* DN_KEY_LT(a,b) returns true if key 'a' is smaller than 'b'43*44* The heap is a struct dn_heap plus a dynamically allocated45* array of dn_heap_entry entries. 'size' represents the size of46* the array, 'elements' count entries in use. The topmost47* element has the smallest key.48* The heap supports ordered insert, and extract from the top.49* To extract an object from the middle of the heap, we the object50* must reserve an 'int32_t' to store the position of the object51* in the heap itself, and the location of this field must be52* passed as an argument to heap_init() -- use -1 if the feature53* is not used.54*/55struct dn_heap_entry {56uint64_t key; /* sorting key, smallest comes first */57void *object; /* object pointer */58};5960struct dn_heap {61int size; /* the size of the array */62int elements; /* elements in use */63int ofs; /* offset in the object of heap index */64struct dn_heap_entry *p; /* array of "size" entries */65};6667enum {68HEAP_SCAN_DEL = 1,69HEAP_SCAN_END = 2,70};7172/*73* heap_init() reinitializes the heap setting the size and the offset74* of the index for random extraction (use -1 if not used).75* The 'elements' counter is set to 0.76*77* SET_HEAP_OFS() indicates where, in the object, is stored the index78* for random extractions from the heap.79*80* heap_free() frees the memory associated to a heap.81*82* heap_insert() adds a key-pointer pair to the heap83*84* HEAP_TOP() returns a pointer to the top element of the heap,85* but makes no checks on its existence (XXX should we change ?)86*87* heap_extract() removes the entry at the top, returning the pointer.88* (the key should have been read before).89*90* heap_scan() invokes a callback on each entry of the heap.91* The callback can return a combination of HEAP_SCAN_DEL and92* HEAP_SCAN_END. HEAP_SCAN_DEL means the current element must93* be removed, and HEAP_SCAN_END means to terminate the scan.94* heap_scan() returns the number of elements removed.95* Because the order is not guaranteed, we should use heap_scan()96* only as a last resort mechanism.97*/98#define HEAP_TOP(h) ((h)->p)99#define SET_HEAP_OFS(h, n) do { (h)->ofs = n; } while (0)100int heap_init(struct dn_heap *h, int size, int ofs);101int heap_insert(struct dn_heap *h, uint64_t key1, void *p);102bool heap_extract(struct dn_heap *h, void *obj);103void heap_free(struct dn_heap *h);104int heap_scan(struct dn_heap *, int (*)(void *, uintptr_t), uintptr_t);105106/*------------------------------------------------------107* This module implements a generic hash table with support for108* running callbacks on the entire table. To avoid allocating109* memory during hash table operations, objects must reserve110* space for a link field. XXX if the heap is moderately full,111* an SLIST suffices, and we can tolerate the cost of a hash112* computation on each removal.113*114* dn_ht_init() initializes the table, setting the number of115* buckets, the offset of the link field, the main callbacks.116* Callbacks are:117*118* hash(key, flags, arg) called to return a bucket index.119* match(obj, key, flags, arg) called to determine if key120* matches the current 'obj' in the heap121* newh(key, flags, arg) optional, used to allocate a new122* object during insertions.123*124* dn_ht_free() frees the heap or unlink elements.125* DNHT_REMOVE unlink elements, 0 frees the heap.126* You need two calls to do both.127*128* dn_ht_find() is the main lookup function, which can also be129* used to insert or delete elements in the hash table.130* The final 'arg' is passed to all callbacks.131*132* dn_ht_scan() is used to invoke a callback on all entries of133* the heap, or possibly on just one bucket. The callback134* is invoked with a pointer to the object, and must return135* one of DNHT_SCAN_DEL or DNHT_SCAN_END to request the136* removal of the object from the heap and the end of the137* scan, respectively.138*139* dn_ht_scan_bucket() is similar to dn_ht_scan(), except that it scans140* only the specific bucket of the table. The bucket is a in-out141* parameter and return a valid bucket number if the original142* is invalid.143*144* A combination of flags can be used to modify the operation145* of the dn_ht_find(), and of the callbacks:146*147* DNHT_KEY_IS_OBJ means the key is the object pointer.148* It is usually of interest for the hash and match functions.149*150* DNHT_MATCH_PTR during a lookup, match pointers instead151* of calling match(). Normally used when removing specific152* entries. Does not imply KEY_IS_OBJ as the latter _is_ used153* by the match function.154*155* DNHT_INSERT insert the element if not found.156* Calls new() to allocates a new object unless157* DNHT_KEY_IS_OBJ is set.158*159* DNHT_UNIQUE only insert if object not found.160* XXX should it imply DNHT_INSERT ?161*162* DNHT_REMOVE remove objects if we find them.163*/164struct dn_ht; /* should be opaque */165166struct dn_ht *dn_ht_init(struct dn_ht *, int buckets, int ofs,167uint32_t (*hash)(uintptr_t, int, void *),168int (*match)(void *, uintptr_t, int, void *),169void *(*newh)(uintptr_t, int, void *));170void dn_ht_free(struct dn_ht *, int flags);171172void *dn_ht_find(struct dn_ht *, uintptr_t, int, void *);173int dn_ht_scan(struct dn_ht *, int (*)(void *, void *), void *);174int dn_ht_scan_bucket(struct dn_ht *, int * , int (*)(void *, void *), void *);175int dn_ht_entries(struct dn_ht *);176177enum { /* flags values.178* first two are returned by the scan callback to indicate179* to delete the matching element or to end the scan180*/181DNHT_SCAN_DEL = 0x0001,182DNHT_SCAN_END = 0x0002,183DNHT_KEY_IS_OBJ = 0x0004, /* key is the obj pointer */184DNHT_MATCH_PTR = 0x0008, /* match by pointer, not match() */185DNHT_INSERT = 0x0010, /* insert if not found */186DNHT_UNIQUE = 0x0020, /* report error if already there */187DNHT_REMOVE = 0x0040, /* remove on find or dn_ht_free */188};189190#endif /* _IP_DN_HEAP_H */191192193