/src/utils/ptr_sets.h

https://github.com/SRI-CSL/yices2 · C Header · 166 lines · 34 code · 32 blank · 100 comment · 1 complexity · bac4e31a3cf8cb7dacb256ff81de53ec MD5 · raw file

  1. /*
  2. * This file is part of the Yices SMT Solver.
  3. * Copyright (C) 2017 SRI International.
  4. *
  5. * Yices is free software: you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation, either version 3 of the License, or
  8. * (at your option) any later version.
  9. *
  10. * Yices is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with Yices. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. /*
  19. * Sets/bags of pointers
  20. * - this supports addition and removal of (void *) pointers.
  21. * All elements in the set must be distinct from NULL and
  22. * DELETED_PTR_ELEM (defined below)
  23. * - the implementation uses an array
  24. * - if the set is small, we just use linear scan of the array
  25. * - when the set becomes large, we switch to a hash table
  26. */
  27. #ifndef __PTR_SETS_H
  28. #define __PTR_SETS_H
  29. #include <stdint.h>
  30. #include <stdbool.h>
  31. #include <stddef.h>
  32. #include "utils/memalloc.h"
  33. /*
  34. * Set descriptor:
  35. * - data = array of n elements where n is a power of two
  36. * - size = n
  37. * - nelems = actual number of elements in data
  38. * - ndeleted = number of deleted elements
  39. */
  40. typedef struct ptr_set_s {
  41. uint32_t size;
  42. uint32_t nelems;
  43. uint32_t ndeleted;
  44. uint32_t resize_threshold;
  45. void *data[0]; // real size = size
  46. } ptr_set_t;
  47. #define DEF_PTR_SET_SIZE 8
  48. #define MAX_PTR_SET_SIZE ((UINT32_MAX-sizeof(ptr_set_t))/sizeof(void *))
  49. /*
  50. * Threshold: when size > SMALL_PTR_SET_SIZE, we switch to
  51. * a hash-table representation.
  52. *
  53. * In hash-table mode, the following thresholds are used:
  54. * - when nelems > size * PTR_SET_RESIZE_RATIO: make the table larger
  55. * - when nelems < size * PTR_SET_SHRINK_RATIO: make the table smaller
  56. */
  57. #define SMALL_PTR_SET_SIZE 32
  58. #define PTR_SET_RESIZE_RATIO 0.7
  59. #define PTR_SET_SHRINK_RATIO 0.3
  60. /*
  61. * Marker for deleted elements
  62. */
  63. #define DELETED_PTR_ELEM ((void *) 1)
  64. /*
  65. * Allocate and initialize a set
  66. * - this creates an empty set of default size
  67. */
  68. extern ptr_set_t *new_ptr_set(void);
  69. /*
  70. * Delete a set descriptor
  71. */
  72. static inline void free_ptr_set(ptr_set_t *s) {
  73. safe_free(s);
  74. }
  75. /*
  76. * Check whether p != NULL && p != DELETED_PTR_ELEM
  77. */
  78. static inline bool live_ptr_elem(void *p) {
  79. return (((uintptr_t) p) >> 1) != (uintptr_t) 0;
  80. }
  81. /*
  82. * Check whether set s contains p
  83. * - s can be NULL here. NULL is interpreted as the empty set.
  84. */
  85. extern bool ptr_set_member(ptr_set_t *s, void *p);
  86. /*
  87. * Add p to the set *s.
  88. * - p must be distinct from NULL and from DELETED_PTR_ELEM
  89. * - if *s is NULL, this function creates a new set of
  90. * default size that contains the singleton { p } and stores
  91. * this new set in *s.
  92. * - if *s is non NULL, then p is added to the set pointed
  93. * to by *s. This may cause of new set descriptor to
  94. * be allocated and stored in *s (and the original set
  95. * is freed).
  96. *
  97. * The function does not check whether p is already present.
  98. * It will add an element to *s no-matter what (so *s may
  99. * contain duplicates).
  100. */
  101. extern void ptr_set_add(ptr_set_t **s, void *p);
  102. /*
  103. * Remove p from set *s
  104. * - p must be distinct from NULL and from DELETED_PTR_ELEM
  105. * - p must be present in *s (so *s must be non-NULL)
  106. * - *s may be updated to a new set descriptor if the removal
  107. * of p causes a reduction in size.
  108. *
  109. * If s contains p multiple times, then only one occurrence
  110. * of p is removed.
  111. */
  112. extern void ptr_set_remove(ptr_set_t **s, void *p);
  113. /*
  114. * Add p to *s if it's not present.
  115. * - updates *s as explained in ptr_set_add
  116. * - returns true if p is added (i.e., p was not in *s when the function was called)
  117. * - returns false otherwise and leaves *s unchanged.
  118. */
  119. extern bool ptr_set_add_if_absent(ptr_set_t **s, void *p);
  120. /*
  121. * Remove p from *s if it's present
  122. * - if p is not present in *s, then *s is unchanged and the function
  123. * returns false.
  124. * - otherwise, one occurrence of p is removed from *s, then *s
  125. * may be updated as in ptr_set_remove, and the function returns true.
  126. */
  127. extern bool ptr_set_remove_if_present(ptr_set_t **s, void *p);
  128. /*
  129. * Iterator: call f(aux, p) for every p stored in s
  130. * - f must not have a side effect on s
  131. */
  132. typedef void (*ptr_set_iterator_t)(void *aux, void *p);
  133. extern void ptr_set_iterate(ptr_set_t *s, void *aux, ptr_set_iterator_t f);
  134. #endif /* __PTR_SETS_H */