OpenSDN source code
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
bitvector.h
Go to the documentation of this file.
1 /* $Id: bitvector.h 346474 2009-11-14 10:18:58Z ssiano $
2  *
3  * bitvector.h - Bit vector manipulation definitions
4  *
5  * Dave Katz, March 2008
6  *
7  * Copyright (c) 2008, Juniper Networks, Inc.
8  * All rights reserved.
9  */
10 
11 /*
12  * Overview
13  *
14  * This module provides generalized manipulation of arbitrary-size
15  * bit vectors. Single-bit operations are provided (set, clear, test,
16  * find) as well as vector set operations (and, or, xor, clear, copy,
17  * walk).
18  *
19  * When performing vector operations, a callback can optionally
20  * be provided that will be called either for every bit in the result
21  * that changes, or any bit that is set after the operation. This allows
22  * for efficient generalized vector operations for which the bit vectors
23  * represent set elements.
24  *
25  * The bit vector is represented by a bit_vector structure, typically
26  * embedded in another structure, to which are attached zero or more
27  * bit vector entries. This allows for sparse bit vectors, as vector
28  * entries are only allocated for bits that are set.
29  *
30  * Vector operations are normally fairly expensive, as per-bit
31  * analysis must be done in order to perform per-bit callbacks and to
32  * keep track of how many bits in each entry are set in order to do
33  * pruning of the tree as entries are completely cleared. However,
34  * vector operations can be significantly sped up if the "fast_vects"
35  * flag is set on the call to bv_init_vector--the vector operations
36  * then become word-sized and no per-bit operations are done. The
37  * downside to this is that pruning the tree of empty blocks does not
38  * generally occur (which can eat memory), and this in turn can slow
39  * down bit-find operations. It is up to the application to weigh the
40  * tradeoffs.
41  *
42  *
43  * Callbacks
44  *
45  * For vector set operations, an optional callback is provided with
46  * the bit number, the old and new values of the bit, and the context
47  * pointer provided by the original caller. If no callback is
48  * supplied, the only action is to store the results of the set
49  * operation.
50  *
51  * If the callback option BV_CALL_SET is used, the callback will be
52  * called for every bit in the result that is set to one. If
53  * BV_CALL_CHANGE is used, the callback will be called for every bit
54  * in the result that changed.
55  *
56  * If a callback is specified, the result vector pointer may be NULL;
57  * in this case the previous value of the result vector is assumed to
58  * be zero for purposes of deciding which bits should be called back
59  * about (and the results of the operation are otherwise discarded.)
60  * Note that in this case, BV_CALL_SET and BV_CALL_CHANGE will give
61  * the same results.
62  *
63  * A callback can do almost anything *except* attempt any operations
64  * of any sort on the result vector, because it will be in an
65  * inconsistent state at the time of the callback. This is enforced
66  * by assertion. Callbacks must glean any information by other means.
67  * A callback may set or clear the current bit in one of the source
68  * vectors, but may not touch any other bit (for the same reason.)
69  */
70 
71 /*
72  * Calling Sequence
73  *
74  * Each bitvector to be manipulated must be first initialized with a call
75  * to bv_init_vector() prior to use. Once initialized, the contents
76  * cannot be manipulated directly, and the structure containing the vector
77  * must not be freed, lest memory leaks result.
78  *
79  * After initialization, any of the single bit or vector operations may be
80  * performed.
81  *
82  * When the vector is no longer needed, either bv_clean() or
83  * bv_clear_all_bits() must be called to clean up and free memory. Once
84  * this is done, the bitvector can be discarded.
85  *
86  *
87  * Initialization:
88  *
89  * bv_init_vector(bit_vector *bv, boolean fast_vects)
90  * Initialize a new bit vector structure. "fast_vects" specifies whether
91  * the caller wishes to use fast vector operations (see above for details.)
92  *
93  * bv_clean(bit_vector *bv)
94  * Clears all bits and frees all memory associated with a bit vector.
95  * This is a fast way to zero a vector, and is also required to avoid
96  * memory leaks before freeing the structure in which the bit_vector
97  * structure is embedded.
98  *
99  *
100  * Bit operations:
101  *
102  * bv_set_bit(bit_vector *bv, bv_bitnum_t bit_number)
103  * Sets the specified bit number. Returns the previous state of the
104  * bit (0 or 1), or -1 of out of memory.
105  *
106  * bv_clear_bit(bit_vector *bv, bv_bitnum_t bit_number)
107  * Clears the specified bit number. Returns the previous state of the
108  * bit (0 or 1), or -1 of out of memory.
109  *
110  * bv_bit_is_set(bit_vector *bv, bv_bitnum_t bit_number)
111  * Returns TRUE if the bit is set, or FALSE if the bit is clear.
112  *
113  * bv_bitnum_t bv_first_set_bit(bit_vector *bv)
114  * Returns the bit number of the first set bit in the vector, or
115  * BV_BAD_BITNUM if no bits are set.
116  *
117  * bv_bitnum_t bv_first_clear_bit(bit_vector *bv)
118  * Returns the bit number of the first clear bit in the vector, or
119  * BV_BAD_BITNUM if the bit vector has all bits set and cannot grow
120  * further. This generally will always succeed.
121  *
122  * bv_bitnum_t bv_find_clear_bit(bit_vector *bv)
123  * Same as bv_first_clear_bit, except that the bit number returned is
124  * not necessarily the first clear bit. This is potentially faster
125  * than bv_first_clear_bit but may be less memory efficient, since
126  * the resulting vector may be more sparse.
127  *
128  * boolean bv_empty(bit_vector *bv)
129  * Returns TRUE if the bit vector is empty (no set bits), or FALSE if
130  * not. This is cheaper than using bv_first_set_bit(), for example.
131  *
132  *
133  * Bit vector vperations
134  *
135  * The following calls allow the manipulation of bit vectors as sets. All
136  * of them have the optional callback as described above. A NULL vector
137  * pointer as a source parameter is treated as vector with all bits clear.
138  * A NULL result pointer means that the caller doesn't actually care about
139  * the results as a vector (a callback is required for this to be anything
140  * other than a way to waste CPU.) Each routine returns 0 if all went
141  * OK, or -1 if we ran out of memory.
142  *
143  * The callback must be defined as follows:
144  *
145  * boolean cb_routine(void *context, bv_bitnum_t bit_number, boolean
146  * new_bit_value, boolean old_bit_value)
147  *
148  * Context is the opaque context passed from the original call to
149  * the vector operation. bit_number is the bit number in the
150  * vector being signaled (either because it is set or because it
151  * changed, depending on the original call.) new_bit_value and
152  * old_bit_value are the old and new values of the bit, which may
153  * be changing, depending on the operation. The callback routine
154  * must return TRUE if the operation is to be aborted (which can
155  * save CPU in some cases) or FALSE if it should continue.
156  *
157  *
158  * The operations are:
159  *
160  * int bv_and_vectors(bit_vector *first, bit_vector *second,
161  * bit_vector *result, bv_callback callback,
162  * void *context, bv_callback_option cb_opt)
163  * int bv_or_vectors(bit_vector *first, bit_vector *second,
164  * bit_vector *result, bv_callback callback,
165  * void *context, bv_callback_option cb_opt)
166  * int bv_xor_vectors(bit_vector *first, bit_vector *second,
167  * bit_vector *result, bv_callback callback,
168  * void *context, bv_callback_option cb_opt)
169  * int bv_clear_vectors(bit_vector *first, bit_vector *second,
170  * bit_vector *result, bv_callback callback,
171  * void *context, bv_callback_option cb_opt)
172  * Performs a boolean AND, OR, XOR, or CLEAR operation between
173  * vectors "first" and "second", storing the results in "result",
174  * with optional callback. (A "clear" operation clears any bit
175  * that is set in the second vector.)
176  *
177  * int bv_copy_vector(bit_vector *src, bit_vector *dest,
178  * bv_callback callback, void *context,
179  * bv_callback_option cb_opt)
180  * Copies the contents of vector "src" to vector "dest", with optional
181  * callback.
182  *
183  * int bv_walk_vector(bit_vector *vect, bv_callback callback, void *context,
184  * bv_callback_option cb_opt)
185  * Walks the bit vector, calling back for every bit set in the vector.
186  *
187  * void bv_clear_all_bits(bit_vector *vect, bv_callback callback,
188  * void *context, bv_callback_option cb_opt)
189  * Clears all bits in the vector (like bv_clean()) but does so with a
190  * callback for each bit that's set in the vector.
191  */
192 
193 
194 /*
195  * Environment
196  *
197  * The bitvector code is a portable source library. It requires certain
198  * services from the environment in which it runs. These services are
199  * called through procedures named bvx_<foo> and are listed below.
200  *
201  * The environment is defined by an application-specific file that is
202  * included by the library called "bvx_environment.h". That file typically
203  * contains #defines and typedefs and externs that bind the toolkit's
204  * calls to the local environment.
205  *
206  * The required definitions are as follows. Note that if the exact type
207  * of parameter or return value is not specified, the toolkit treats it in
208  * a generic way and does not explicitly type it (for instance, zero/nonzero
209  * procedure returns.)
210  *
211  * Patricia library:
212  *
213  * bvx_patroot
214  * An opaque type for a patricia root structure
215  *
216  * bvx_patnode
217  * An opaque type for a patricia node
218  *
219  * bvx_patroot *bvx_patroot_init(keylen, offset)
220  * Initializes a patricia root. Keylen is the length of the key in bytes.
221  * Offset is the byte offset from the start of the key to the start of
222  * the patricia node.
223  *
224  * bvx_patnode *bvx_patricia_lookup(bvx_patroot *root, void *key)
225  * Looks up a patricia entry, returns a pointer to the patricia node,
226  * or NULL if not found.
227  *
228  * bvx_patnode *bvx_patricia_lookup_least(bvx_patroot *root)
229  * Looks up the first entry in a patricia tree, returns a pointer to the
230  * patricia node, or NULL if the tree is empty.
231  *
232  * bvx_patnode *bvx_patricia_lookup_greatest(bvx_patroot *root)
233  * Looks up the last entry in a patricia tree, returns a pointer to the
234  * patricia node, or NULL if the tree is empty.
235  *
236  * bvx_patricia_add(bvx_patroot *root, bvx_patnode *node)
237  * Adds the node to the patricia tree. Returns nonzero if successful,
238  * zero if failed (e.g., key already in the tree).
239  *
240  * bvx_patricia_delete(bvx_patroot *root, bvx_patnode *node)
241  * Deletes the node from the patricia tree. Returns nonzero if successful,
242  * zero if failed (e.g., node is not in the tree).
243  *
244  * bvx_patnode *bvx_patricia_get_next(bvx_patroot *root, bvx_patnode *node)
245  * Returns the patricia node following the specified one. If the specified
246  * node is NULL, returns the first node in the tree. Returns NULL if there
247  * are no more nodes in the tree.
248  *
249  * bvx_patroot_destroy(bvx_patroot *root)
250  * Destroys the patricia tree root. The toolkit ensures that all nodes are
251  * first deleted from the tree.
252  *
253  * BVX_PATRICIA_OFFSET(structname, nodefield, keyfield)
254  * Returns the offset in a structure from the patricia node to the
255  * patricia key. This should resolve to a bunch of pointer math. This
256  * is used in calls to bvx_patroot_init().
257  *
258  * BVX_PATNODE_TO_STRUCT(procname, structname, nodefieldname)
259  * Creates an inline procedure that, given a pointer to an embedded
260  * bvx_patnode in a structure, returns a pointer to the enclosing
261  * structure, or returns NULL if the node pointer is NULL.
262  *
263  *
264  * Thread Library:
265  *
266  * The library for doubly-linked-list data structure.
267  *
268  *
269  * Memory management:
270  *
271  * The bitvector toolkit expects a block memory management system, in which
272  * a block size is first defined, and then requests for specific block sizes
273  * are made thereafter (modeled on rpd's memory manager.)
274  *
275  * bvx_block_tag
276  * An opaque type that defines a tag representing a memory block size.
277  * Semantically, this is the size itself (and in fact a sleazy way to
278  * implement this in a naked malloc() environment is to define this as
279  * an int and simply store the block size here.) The tag must be a
280  * scalar (so that it can be compared to zero) and it must be nonzero
281  * when it is valid (since a zero value implies an uninitialized tag.)
282  *
283  * bvx_block_tag bvx_malloc_block_create(size, const char *name)
284  * Create a block tag for memory blocks of a particular size. The name
285  * can be used for diagnostic purposes. Returns the tag.
286  *
287  * void *bvx_malloc_block(bvx_block_tag tag)
288  * Allocate a block of memory of the size denoted by the tag. Returns
289  * a pointer to the block, or NULL if out of memory. The toolkit
290  * does not specify the pointer type of the returned value, but expects
291  * to be able to assign it to any pointer type without coercion (thus
292  * the void *).
293  *
294  * bvx_free_block(bvx_block_tag tag, void *block)
295  * Free a block of memory to the size pool specified by the tag.
296  *
297  *
298  * Miscellaneous stuff:
299  *
300  * bvx_assert(condition)
301  * Crashes if the condition is not true.
302  *
303  * BVX_UNUSED
304  * Used in procedure declarations after unused parameters to avoid
305  * generating compilation warnings, e.g. "int flort(int foo BVX_UNUSED)".
306  *
307  * uint32_t
308  * Must be typedefed to an unsigned, 32 bit scalar.
309  *
310  * boolean, TRUE, FALSE
311  * The boolean type and the TRUE and FALSE constants must be defined.
312  * TRUE must be nonzero, and FALSE must be zero. There is no assumption
313  * about the size of the boolean type.
314  *
315  *
316  * Size definitions:
317  *
318  * The bitvector toolkit requires two items to be specified that impact
319  * how memory is used by the toolkit. They are:
320  *
321  * BV_BITSIZE_LOG2
322  * The base-2 log of the size of a bit vector entry.
323  *
324  * bv_word_t
325  * A type defining the size of a scalar word.
326  *
327  * BV_BITSIZE_LOG2 must be greater than or equal to the base 2 log of the
328  * bit size of bv_word_t. So if bv_word_t is typedefed as a uint32_t,
329  * BV_BITSIZE_LOG2 must be greater than or equal to 5.
330  *
331  * BV_BITSIZE_LOG2 represents the granularity of memory allocated to maintain
332  * the bit vector. Larger values provide lower overhead when using sparse
333  * arrays (since the number of individual memory blocks and the size of the
334  * patricia tree will be smaller), but waste memory if the vector is very
335  * sparse or has very few bits set.
336  *
337  * bv_word_t represents the size of a scalar in which bits are stored. This
338  * type needs to be able to be compared to zero, for example. This ought
339  * to match the largest native scalar type on the processor in use that
340  * is small enough to fit within BV_BITSIZE_LOG2.
341  */
342 
343 #ifndef __BITVECTOR_H__
344 #define __BITVECTOR_H__
345 
346 /*
347  * Bit vector
348  *
349  * A bit vector is a patricia tree of bit vector entries.
350  *
351  * An empty tree may have a null root pointer.
352  *
353  * bv_fastvects is set if the application wants to do fast vector operations
354  * (but see the comments in the front of this file regarding the tradeoffs.)
355  * The side effect of setting bv_fastvects is that the bit count in a vector
356  * entry may become unknown, which in turn means that completely empty
357  * entries may be left in the tree, and that non-full entries may not end
358  * up in the non-full list. This impacts the cost of a search for free
359  * bits.
360  *
361  * bv_nonfull_head is an optimization to help searches for clear bits.
362  * Normally, all entries that aren't full are threaded there in order
363  * to make searching for a free bit cheap. However, if vector
364  * operations are in effect, this list may be incomplete.
365  *
366  * bv_freed_ord is also an optimization to help searches for clear
367  * bits. This is set to be either the starting bit ordinal of a free
368  * (nonexistent) block of bits, or BV_BAD_BITNUM if it is unset. The
369  * code endeavors to keep this set cheaply; it is used as a free bit
370  * number if no allocated blocks with free bits are available.
371  */
372 
373 typedef uint32_t bv_bitnum_t; /* Bit number */
374 #define BV_BAD_BITNUM 0xffffffff /* Illegal bit number */
375 
376 typedef struct bit_vector_ {
377  bvx_patroot *bv_root; /* Patricia root */
378  uint32_t bv_entry_count; /* Number of attached entries */
379  task_thread bv_nonfull_head; /* Head of non-full entries */
380  bv_bitnum_t bv_callback_ord; /* Ordinal of callback bit */
381  bv_bitnum_t bv_freed_ord; /* Ordinal of a freed entry */
382  boolean bv_fastvects; /* Perform fast vector operations */
383  boolean bv_cb_result; /* TRUE if vector is callback result */
384  boolean bv_cb_source; /* TRUE if vector is callback source */
385 } bit_vector;
386 
387 /*
388  * Bit vector callback definition. The bit vector routines can call
389  * back to an application as the results of bit vector manipulations
390  * are generated.
391  *
392  * If the callback returns TRUE, the set operation is aborted. This can
393  * save time in some situations.
394  */
395 typedef boolean (*bv_callback)(void *context, bv_bitnum_t bit_number,
396  boolean new_bit_value, boolean old_bit_value);
397 
398 
399 
400 /*
401  * Definitions of bit result callback options.
402  */
403 typedef enum {
404  BV_CALL_CHANGE, /* Call back if result bit changed */
405  BV_CALL_SET /* Call back if result bit is set */
407 
408 /* Externals */
409 
410 extern void bv_clean(bit_vector *bv);
411 extern int bv_set_bit(bit_vector *bv, bv_bitnum_t bit_number);
412 extern boolean bv_clear_bit(bit_vector *bv, bv_bitnum_t bit_number);
413 extern boolean bv_bit_is_set(bit_vector *bv, bv_bitnum_t bit_number);
414 extern void bv_init_vector(bit_vector *bv, boolean fast_vects);
415 extern int bv_and_vectors(bit_vector *first, bit_vector *second,
416  bit_vector *result, bv_callback callback,
417  void *context, bv_callback_option cb_opt);
418 extern int bv_or_vectors(bit_vector *first, bit_vector *second,
419  bit_vector *result, bv_callback callback,
420  void *context, bv_callback_option cb_opt);
421 extern int bv_xor_vectors(bit_vector *first, bit_vector *second,
422  bit_vector *result, bv_callback callback,
423  void *context, bv_callback_option cb_opt);
424 extern int bv_clear_vectors(bit_vector *first, bit_vector *second,
425  bit_vector *result, bv_callback callback,
426  void *context, bv_callback_option cb_opt);
427 extern int bv_copy_vector(bit_vector *src, bit_vector *dest,
428  bv_callback callback, void *context,
429  bv_callback_option cb_opt);
430 extern int bv_walk_vector(bit_vector *vect, bv_callback callback,
431  void *context);
433 extern boolean bv_empty(bit_vector *bv);
436 extern void bv_clear_all_bits(bit_vector *bv, bv_callback callback,
437  void *context, bv_callback_option cb_opt);
438 
439 #endif /* __BITVECTOR_H__ */
void bv_clean(bit_vector *bv)
uint32_t bv_entry_count
Definition: bitvector.h:378
int bv_and_vectors(bit_vector *first, bit_vector *second, bit_vector *result, bv_callback callback, void *context, bv_callback_option cb_opt)
bvx_patroot * bv_root
Definition: bitvector.h:377
boolean bv_cb_source
Definition: bitvector.h:384
boolean bv_bit_is_set(bit_vector *bv, bv_bitnum_t bit_number)
struct bit_vector_ bit_vector
boolean bv_cb_result
Definition: bitvector.h:383
boolean bv_empty(bit_vector *bv)
unsigned int boolean
Definition: mcast_common.h:11
boolean(* bv_callback)(void *context, bv_bitnum_t bit_number, boolean new_bit_value, boolean old_bit_value)
Definition: bitvector.h:395
boolean bv_clear_bit(bit_vector *bv, bv_bitnum_t bit_number)
int bv_copy_vector(bit_vector *src, bit_vector *dest, bv_callback callback, void *context, bv_callback_option cb_opt)
void bv_clear_all_bits(bit_vector *bv, bv_callback callback, void *context, bv_callback_option cb_opt)
bv_bitnum_t bv_first_clear_bit(bit_vector *bv)
int bv_set_bit(bit_vector *bv, bv_bitnum_t bit_number)
void bv_init_vector(bit_vector *bv, boolean fast_vects)
bv_callback_option
Definition: bitvector.h:403
boolean bv_fastvects
Definition: bitvector.h:382
bv_bitnum_t bv_freed_ord
Definition: bitvector.h:381
task_thread bv_nonfull_head
Definition: bitvector.h:379
bv_bitnum_t bv_find_clear_bit(bit_vector *bv)
#define bvx_patroot
int bv_or_vectors(bit_vector *first, bit_vector *second, bit_vector *result, bv_callback callback, void *context, bv_callback_option cb_opt)
int bv_walk_vector(bit_vector *vect, bv_callback callback, void *context)
int bv_clear_vectors(bit_vector *first, bit_vector *second, bit_vector *result, bv_callback callback, void *context, bv_callback_option cb_opt)
bv_bitnum_t bv_callback_ord
Definition: bitvector.h:380
uint32_t bv_bitnum_t
Definition: bitvector.h:373
int bv_xor_vectors(bit_vector *first, bit_vector *second, bit_vector *result, bv_callback callback, void *context, bv_callback_option cb_opt)
bv_bitnum_t bv_first_set_bit(bit_vector *bv)