Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
don't malloc tons of dynars in mpi_waitany
[simgrid.git] / src / xbt / dynar.cpp
index dbd8961..375b1c5 100644 (file)
@@ -18,7 +18,7 @@ XBT_LOG_NEW_DEFAULT_SUBCATEGORY(xbt_dyn, xbt, "Dynamic arrays");
 
 static inline void _sanity_check_dynar(xbt_dynar_t dynar)
 {
-  xbt_assert(dynar, "dynar is NULL");
+  xbt_assert(dynar, "dynar is nullptr");
 }
 
 static inline void _sanity_check_idx(int idx)
@@ -84,7 +84,7 @@ void xbt_dynar_dump(xbt_dynar_t dynar)
 /** @brief Constructor
  *
  * \param elmsize size of each element in the dynar
- * \param free_f function to call each time we want to get rid of an element (or NULL if nothing to do).
+ * \param free_f function to call each time we want to get rid of an element (or nullptr if nothing to do).
  *
  * Creates a new dynar. If a free_func is provided, the elements have to be pointer of pointer. That is to say that
  * dynars can contain either base types (int, char, double, etc) or pointer of pointers (struct **).
@@ -96,12 +96,24 @@ xbt_dynar_t xbt_dynar_new(const unsigned long elmsize, void_f_pvoid_t const free
   dynar->size = 0;
   dynar->used = 0;
   dynar->elmsize = elmsize;
-  dynar->data = NULL;
+  dynar->data = nullptr;
   dynar->free_f = free_f;
 
   return dynar;
 }
 
+/** @brief Initialize a dynar structure that was not malloc'ed
+ * This can be useful to keep temporary dynars on the stack
+ */
+void xbt_dynar_init(xbt_dynar_t dynar, const unsigned long elmsize, void_f_pvoid_t const free_f)
+{
+  dynar->size    = 0;
+  dynar->used    = 0;
+  dynar->elmsize = elmsize;
+  dynar->data    = nullptr;
+  dynar->free_f  = free_f;
+}
+
 /** @brief Destructor of the structure not touching to the content
  *
  * \param dynar poor victim
@@ -115,7 +127,7 @@ void xbt_dynar_free_container(xbt_dynar_t * dynar)
     xbt_dynar_t d = *dynar;
     free(d->data);
     free(d);
-    *dynar = NULL;
+    *dynar = nullptr;
   }
 }
 
@@ -371,7 +383,7 @@ void xbt_dynar_remove_at(xbt_dynar_t const dynar, const int idx, void *const obj
 /** @brief Remove a slice of the dynar, sliding the rest of the values to the left
  *
  * This function removes an n-sized slice that starts at element idx. It is equivalent to xbt_dynar_remove_at with a
- * NULL object argument if n equals to 1.
+ * nullptr object argument if n equals to 1.
  *
  * Each of the removed elements is freed using the free_f function passed at dynar creation.
  */
@@ -461,15 +473,14 @@ signed int xbt_dynar_search_or_negative(xbt_dynar_t const dynar, void *const ele
  */
 int xbt_dynar_member(xbt_dynar_t const dynar, void *const elem)
 {
-  try {
-    xbt_dynar_search(dynar, elem);
-  }
-  catch (xbt_ex& e) {
-    if (e.category == not_found_error)
-      return 0;
-    throw;
-  }
-  return 1;
+  unsigned long it;
+
+  for (it = 0; it < dynar->used; it++)
+    if (!memcmp(_xbt_dynar_elm(dynar, it), elem, dynar->elmsize)) {
+      return 1;
+    }
+
+  return 0;
 }
 
 /** @brief Make room at the end of the dynar for a new element, and return a pointer to it.
@@ -555,7 +566,7 @@ void xbt_dynar_map(const xbt_dynar_t dynar, void_f_pvoid_t const op)
  */
 void xbt_dynar_cursor_rm(xbt_dynar_t dynar, unsigned int *const cursor)
 {
-  xbt_dynar_remove_at(dynar, (*cursor)--, NULL);
+  xbt_dynar_remove_at(dynar, (*cursor)--, nullptr);
 }
 
 /** @brief Sorts a dynar according to the function <tt>compar_fn</tt>
@@ -621,7 +632,7 @@ XBT_PUBLIC(void) xbt_dynar_three_way_partition(xbt_dynar_t const dynar, int_f_pv
   unsigned long int p = -1;
   unsigned long int q = dynar->used;
   const unsigned long elmsize = dynar->elmsize;
-  void *tmp = xbt_malloc(elmsize);
+  char* tmp[elmsize];
   void *elm;
 
   for (i = 0; i < q;) {
@@ -644,10 +655,9 @@ XBT_PUBLIC(void) xbt_dynar_three_way_partition(xbt_dynar_t const dynar, int_f_pv
       }
     }
   }
-  xbt_free(tmp);
 }
 
-/** @brief Transform a dynar into a NULL terminated array. 
+/** @brief Transform a dynar into a nullptr terminated array. 
  *
  *  \param dynar the dynar to transform
  *  \return pointer to the first element of the array
@@ -682,7 +692,7 @@ int xbt_dynar_compare(xbt_dynar_t d1, xbt_dynar_t d2, int(*compar)(const void *,
   if((!d1) && (!d2)) return 0;
   if((!d1) || (!d2))
   {
-    XBT_DEBUG("NULL dynar d1=%p d2=%p",d1,d2);
+    XBT_DEBUG("nullptr dynar d1=%p d2=%p",d1,d2);
     xbt_dynar_free(&d2);
     return 1;
   }
@@ -721,13 +731,12 @@ XBT_LOG_EXTERNAL_DEFAULT_CATEGORY(xbt_dyn);
 XBT_TEST_UNIT("int", test_dynar_int, "Dynars of integers")
 {
   /* Vars_decl [doxygen cruft] */
-  xbt_dynar_t d;
-  int i, cpt;
+  int i;
   unsigned int cursor;
   int *iptr;
 
   xbt_test_add("==== Traverse the empty dynar");
-  d = xbt_dynar_new(sizeof(int), NULL);
+  xbt_dynar_t d = xbt_dynar_new(sizeof(int), nullptr);
   xbt_dynar_foreach(d, cursor, i) {
     xbt_die( "Damnit, there is something in the empty dynar");
   }
@@ -738,8 +747,8 @@ XBT_TEST_UNIT("int", test_dynar_int, "Dynars of integers")
   xbt_test_add("==== Push %d int, set them again 3 times, traverse them, shift them", NB_ELEM);
   /* Populate_ints [doxygen cruft] */
   /* 1. Populate the dynar */
-  d = xbt_dynar_new(sizeof(int), NULL);
-  for (cpt = 0; cpt < NB_ELEM; cpt++) {
+  d = xbt_dynar_new(sizeof(int), nullptr);
+  for (int cpt = 0; cpt < NB_ELEM; cpt++) {
     xbt_dynar_push_as(d, int, cpt);     /* This is faster (and possible only with scalars) */
     /* xbt_dynar_push(d,&cpt);       This would also work */
     xbt_test_log("Push %d, length=%lu", cpt, xbt_dynar_length(d));
@@ -748,23 +757,25 @@ XBT_TEST_UNIT("int", test_dynar_int, "Dynars of integers")
   /* 2. Traverse manually the dynar */
   for (cursor = 0; cursor < NB_ELEM; cursor++) {
     iptr = (int*) xbt_dynar_get_ptr(d, cursor);
-    xbt_test_assert(cursor == (unsigned int) *iptr, "The retrieved value is not the same than the injected one (%u!=%d)", cursor, cpt);
+    xbt_test_assert(cursor == (unsigned int)*iptr, "The retrieved value is not the same than the injected one (%u!=%d)",
+                    cursor, *iptr);
   }
 
   /* 3. Traverse the dynar using the neat macro to that extend */
+  int cpt;
   xbt_dynar_foreach(d, cursor, cpt) {
     xbt_test_assert(cursor == (unsigned int) cpt, "The retrieved value is not the same than the injected one (%u!=%d)", cursor, cpt);
   }
   /* end_of_traversal */
 
-  for (cpt = 0; cpt < NB_ELEM; cpt++)
+  for (int cpt = 0; cpt < NB_ELEM; cpt++)
     *(int *) xbt_dynar_get_ptr(d, cpt) = cpt;
 
-  for (cpt = 0; cpt < NB_ELEM; cpt++)
+  for (int cpt = 0; cpt < NB_ELEM; cpt++)
     *(int *) xbt_dynar_get_ptr(d, cpt) = cpt;
   /*     xbt_dynar_set(d,cpt,&cpt); */
 
-  for (cpt = 0; cpt < NB_ELEM; cpt++)
+  for (int cpt = 0; cpt < NB_ELEM; cpt++)
     *(int *) xbt_dynar_get_ptr(d, cpt) = cpt;
 
   cpt = 0;
@@ -776,7 +787,7 @@ XBT_TEST_UNIT("int", test_dynar_int, "Dynars of integers")
 
   /* shifting [doxygen cruft] */
   /* 4. Shift all the values */
-  for (cpt = 0; cpt < NB_ELEM; cpt++) {
+  for (int cpt = 0; cpt < NB_ELEM; cpt++) {
     xbt_dynar_shift(d, &i);
     xbt_test_assert(i == cpt, "The retrieved value is not the same than the injected one (%d!=%d)", i, cpt);
     xbt_test_log("Pop %d, length=%lu", cpt, xbt_dynar_length(d));
@@ -802,12 +813,12 @@ XBT_TEST_UNIT("int", test_dynar_int, "Dynars of integers")
   /* in your code is naturally the way to go outside a regression test */
 
   xbt_test_add("==== Unshift/pop %d int", NB_ELEM);
-  d = xbt_dynar_new(sizeof(int), NULL);
-  for (cpt = 0; cpt < NB_ELEM; cpt++) {
+  d = xbt_dynar_new(sizeof(int), nullptr);
+  for (int cpt = 0; cpt < NB_ELEM; cpt++) {
     xbt_dynar_unshift(d, &cpt);
     XBT_DEBUG("Push %d, length=%lu", cpt, xbt_dynar_length(d));
   }
-  for (cpt = 0; cpt < NB_ELEM; cpt++) {
+  for (int cpt = 0; cpt < NB_ELEM; cpt++) {
     i = xbt_dynar_pop_as(d, int);
     xbt_test_assert(i == cpt, "The retrieved value is not the same than the injected one (%d!=%d)", i, cpt);
     xbt_test_log("Pop %d, length=%lu", cpt, xbt_dynar_length(d));
@@ -817,7 +828,7 @@ XBT_TEST_UNIT("int", test_dynar_int, "Dynars of integers")
   /* in your code is naturally the way to go outside a regression test */
 
   xbt_test_add ("==== Push %d int, insert 1000 int in the middle, shift everything", NB_ELEM);
-  d = xbt_dynar_new(sizeof(int), NULL);
+  d = xbt_dynar_new(sizeof(int), nullptr);
   for (cpt = 0; cpt < NB_ELEM; cpt++) {
     xbt_dynar_push_as(d, int, cpt);
     XBT_DEBUG("Push %d, length=%lu", cpt, xbt_dynar_length(d));
@@ -847,7 +858,7 @@ XBT_TEST_UNIT("int", test_dynar_int, "Dynars of integers")
   /* in your code is naturally the way to go outside a regression test */
 
   xbt_test_add("==== Push %d int, remove 2000-4000. free the rest", NB_ELEM);
-  d = xbt_dynar_new(sizeof(int), NULL);
+  d = xbt_dynar_new(sizeof(int), nullptr);
   for (cpt = 0; cpt < NB_ELEM; cpt++)
     xbt_dynar_push_as(d, int, cpt);
 
@@ -864,31 +875,31 @@ XBT_TEST_UNIT("int", test_dynar_int, "Dynars of integers")
 /*******************************************************************************/
 XBT_TEST_UNIT("insert",test_dynar_insert,"Using the xbt_dynar_insert and xbt_dynar_remove functions")
 {
-  xbt_dynar_t d = xbt_dynar_new(sizeof(unsigned int), NULL);
+  xbt_dynar_t d = xbt_dynar_new(sizeof(unsigned int), nullptr);
   unsigned int cursor;
-  int cpt;
 
   xbt_test_add("==== Insert %d int, traverse them, remove them",NB_ELEM);
   /* Populate_ints [doxygen cruft] */
   /* 1. Populate the dynar */
-  for (cpt = 0; cpt < NB_ELEM; cpt++) {
+  for (int cpt = 0; cpt < NB_ELEM; cpt++) {
     xbt_dynar_insert_at(d, cpt, &cpt);
     xbt_test_log("Push %d, length=%lu", cpt, xbt_dynar_length(d));
   }
 
   /* 3. Traverse the dynar */
+  int cpt;
   xbt_dynar_foreach(d, cursor, cpt) {
     xbt_test_assert(cursor == (unsigned int) cpt, "The retrieved value is not the same than the injected one (%u!=%d)", cursor, cpt);
   }
   /* end_of_traversal */
 
   /* Re-fill with the same values using set_as (and re-verify) */
-  for (cpt = 0; cpt < NB_ELEM; cpt++)
+  for (int cpt = 0; cpt < NB_ELEM; cpt++)
     xbt_dynar_set_as(d, cpt, int, cpt);
   xbt_dynar_foreach(d, cursor, cpt)
     xbt_test_assert(cursor == (unsigned int) cpt, "The retrieved value is not the same than the injected one (%u!=%d)", cursor, cpt);
 
-  for (cpt = 0; cpt < NB_ELEM; cpt++) {
+  for (int cpt = 0; cpt < NB_ELEM; cpt++) {
     int val;
     xbt_dynar_remove_at(d,0,&val);
     xbt_test_assert(cpt == val, "The retrieved value is not the same than the injected one (%u!=%d)", cursor, cpt);
@@ -899,8 +910,8 @@ XBT_TEST_UNIT("insert",test_dynar_insert,"Using the xbt_dynar_insert and xbt_dyn
 
   /* ********************* */
   xbt_test_add("==== Insert %d int in reverse order, traverse them, remove them",NB_ELEM);
-  d = xbt_dynar_new(sizeof(int), NULL);
-  for (cpt = NB_ELEM-1; cpt >=0; cpt--) {
+  d = xbt_dynar_new(sizeof(int), nullptr);
+  for (int cpt = NB_ELEM - 1; cpt >= 0; cpt--) {
     xbt_dynar_replace(d, cpt, &cpt);
     xbt_test_log("Push %d, length=%lu", cpt, xbt_dynar_length(d));
   }
@@ -930,7 +941,7 @@ XBT_TEST_UNIT("double", test_dynar_double, "Dynars of doubles")
   double d1, d2;
 
   xbt_test_add("==== Traverse the empty dynar");
-  d = xbt_dynar_new(sizeof(int), NULL);
+  d = xbt_dynar_new(sizeof(int), nullptr);
   xbt_dynar_foreach(d, cursor, cpt) {
     xbt_test_assert(FALSE, "Damnit, there is something in the empty dynar");
   }
@@ -939,7 +950,7 @@ XBT_TEST_UNIT("double", test_dynar_double, "Dynars of doubles")
   /* in your code is naturally the way to go outside a regression test */
 
   xbt_test_add("==== Push/shift 5000 doubles");
-  d = xbt_dynar_new(sizeof(double), NULL);
+  d = xbt_dynar_new(sizeof(double), nullptr);
   for (cpt = 0; cpt < 5000; cpt++) {
     d1 = (double) cpt;
     xbt_dynar_push(d, &d1);
@@ -958,7 +969,7 @@ XBT_TEST_UNIT("double", test_dynar_double, "Dynars of doubles")
   /* in your code is naturally the way to go outside a regression test */
 
   xbt_test_add("==== Unshift/pop 5000 doubles");
-  d = xbt_dynar_new(sizeof(double), NULL);
+  d = xbt_dynar_new(sizeof(double), nullptr);
   for (cpt = 0; cpt < 5000; cpt++) {
     d1 = (double) cpt;
     xbt_dynar_unshift(d, &d1);
@@ -973,7 +984,7 @@ XBT_TEST_UNIT("double", test_dynar_double, "Dynars of doubles")
   /* in your code is naturally the way to go outside a regression test */
 
   xbt_test_add("==== Push 5000 doubles, insert 1000 doubles in the middle, shift everything");
-  d = xbt_dynar_new(sizeof(double), NULL);
+  d = xbt_dynar_new(sizeof(double), nullptr);
   for (cpt = 0; cpt < 5000; cpt++) {
     d1 = (double) cpt;
     xbt_dynar_push(d, &d1);
@@ -1006,7 +1017,7 @@ XBT_TEST_UNIT("double", test_dynar_double, "Dynars of doubles")
   /* in your code is naturally the way to go outside a regression test */
 
   xbt_test_add("==== Push 5000 double, remove 2000-4000. free the rest");
-  d = xbt_dynar_new(sizeof(double), NULL);
+  d = xbt_dynar_new(sizeof(double), nullptr);
   for (cpt = 0; cpt < 5000; cpt++) {
     d1 = (double) cpt;
     xbt_dynar_push(d, &d1);
@@ -1026,14 +1037,12 @@ XBT_TEST_UNIT("double", test_dynar_double, "Dynars of doubles")
 /*******************************************************************************/
 XBT_TEST_UNIT("string", test_dynar_string, "Dynars of strings")
 {
-  xbt_dynar_t d;
-  int cpt;
   unsigned int iter;
   char buf[1024];
   char *s1, *s2;
 
   xbt_test_add("==== Traverse the empty dynar");
-  d = xbt_dynar_new(sizeof(char *), &xbt_free_ref);
+  xbt_dynar_t d = xbt_dynar_new(sizeof(char*), &xbt_free_ref);
   xbt_dynar_foreach(d, iter, s1) {
     xbt_test_assert(FALSE, "Damnit, there is something in the empty dynar");
   }
@@ -1045,27 +1054,27 @@ XBT_TEST_UNIT("string", test_dynar_string, "Dynars of strings")
   /* Populate_str [doxygen cruft] */
   d = xbt_dynar_new(sizeof(char *), &xbt_free_ref);
   /* 1. Populate the dynar */
-  for (cpt = 0; cpt < NB_ELEM; cpt++) {
+  for (int cpt = 0; cpt < NB_ELEM; cpt++) {
     snprintf(buf,1023, "%d", cpt);
     s1 = xbt_strdup(buf);
     xbt_dynar_push(d, &s1);
   }
-  for (cpt = 0; cpt < NB_ELEM; cpt++) {
+  for (int cpt = 0; cpt < NB_ELEM; cpt++) {
     snprintf(buf,1023, "%d", cpt);
     s1 = xbt_strdup(buf);
     xbt_dynar_replace(d, cpt, &s1);
   }
-  for (cpt = 0; cpt < NB_ELEM; cpt++) {
+  for (int cpt = 0; cpt < NB_ELEM; cpt++) {
     snprintf(buf,1023, "%d", cpt);
     s1 = xbt_strdup(buf);
     xbt_dynar_replace(d, cpt, &s1);
   }
-  for (cpt = 0; cpt < NB_ELEM; cpt++) {
+  for (int cpt = 0; cpt < NB_ELEM; cpt++) {
     snprintf(buf,1023, "%d", cpt);
     s1 = xbt_strdup(buf);
     xbt_dynar_replace(d, cpt, &s1);
   }
-  for (cpt = 0; cpt < NB_ELEM; cpt++) {
+  for (int cpt = 0; cpt < NB_ELEM; cpt++) {
     snprintf(buf,1023, "%d", cpt);
     xbt_dynar_shift(d, &s2);
     xbt_test_assert(!strcmp(buf, s2), "The retrieved value is not the same than the injected one (%s!=%s)", buf, s2);
@@ -1077,7 +1086,7 @@ XBT_TEST_UNIT("string", test_dynar_string, "Dynars of strings")
 
   xbt_test_add("==== Unshift, traverse and pop %d strings", NB_ELEM);
   d = xbt_dynar_new(sizeof(char **), &xbt_free_ref);
-  for (cpt = 0; cpt < NB_ELEM; cpt++) {
+  for (int cpt = 0; cpt < NB_ELEM; cpt++) {
     snprintf(buf,1023, "%d", cpt);
     s1 = xbt_strdup(buf);
     xbt_dynar_unshift(d, &s1);
@@ -1088,7 +1097,7 @@ XBT_TEST_UNIT("string", test_dynar_string, "Dynars of strings")
     xbt_test_assert(!strcmp(buf, s1), "The retrieved value is not the same than the injected one (%s!=%s)", buf, s1);
   }
   /* 3. Traverse the dynar with the macro */
-  for (cpt = 0; cpt < NB_ELEM; cpt++) {
+  for (int cpt = 0; cpt < NB_ELEM; cpt++) {
     snprintf(buf,1023, "%d", cpt);
     xbt_dynar_pop(d, &s2);
     xbt_test_assert(!strcmp(buf, s2), "The retrieved value is not the same than the injected one (%s!=%s)", buf, s2);
@@ -1101,32 +1110,32 @@ XBT_TEST_UNIT("string", test_dynar_string, "Dynars of strings")
 
   xbt_test_add("==== Push %d strings, insert %d strings in the middle, shift everything", NB_ELEM, NB_ELEM / 5);
   d = xbt_dynar_new(sizeof(char *), &xbt_free_ref);
-  for (cpt = 0; cpt < NB_ELEM; cpt++) {
+  for (int cpt = 0; cpt < NB_ELEM; cpt++) {
     snprintf(buf,1023, "%d", cpt);
     s1 = xbt_strdup(buf);
     xbt_dynar_push(d, &s1);
   }
-  for (cpt = 0; cpt < NB_ELEM / 5; cpt++) {
+  for (int cpt = 0; cpt < NB_ELEM / 5; cpt++) {
     snprintf(buf,1023, "%d", cpt);
     s1 = xbt_strdup(buf);
     xbt_dynar_insert_at(d, NB_ELEM / 2, &s1);
   }
 
-  for (cpt = 0; cpt < NB_ELEM / 2; cpt++) {
+  for (int cpt = 0; cpt < NB_ELEM / 2; cpt++) {
     snprintf(buf,1023, "%d", cpt);
     xbt_dynar_shift(d, &s2);
     xbt_test_assert(!strcmp(buf, s2),
                      "The retrieved value is not the same than the injected one at the begining (%s!=%s)", buf, s2);
     free(s2);
   }
-  for (cpt = (NB_ELEM / 5) - 1; cpt >= 0; cpt--) {
+  for (int cpt = (NB_ELEM / 5) - 1; cpt >= 0; cpt--) {
     snprintf(buf,1023, "%d", cpt);
     xbt_dynar_shift(d, &s2);
     xbt_test_assert(!strcmp(buf, s2),
                      "The retrieved value is not the same than the injected one in the middle (%s!=%s)", buf, s2);
     free(s2);
   }
-  for (cpt = NB_ELEM / 2; cpt < NB_ELEM; cpt++) {
+  for (int cpt = NB_ELEM / 2; cpt < NB_ELEM; cpt++) {
     snprintf(buf,1023, "%d", cpt);
     xbt_dynar_shift(d, &s2);
     xbt_test_assert(!strcmp(buf, s2), "The retrieved value is not the same than the injected one at the end (%s!=%s)",
@@ -1139,12 +1148,12 @@ XBT_TEST_UNIT("string", test_dynar_string, "Dynars of strings")
 
   xbt_test_add("==== Push %d strings, remove %d-%d. free the rest", NB_ELEM, 2 * (NB_ELEM / 5), 4 * (NB_ELEM / 5));
   d = xbt_dynar_new(sizeof(char *), &xbt_free_ref);
-  for (cpt = 0; cpt < NB_ELEM; cpt++) {
+  for (int cpt = 0; cpt < NB_ELEM; cpt++) {
     snprintf(buf,1023, "%d", cpt);
     s1 = xbt_strdup(buf);
     xbt_dynar_push(d, &s1);
   }
-  for (cpt = 2 * (NB_ELEM / 5); cpt < 4 * (NB_ELEM / 5); cpt++) {
+  for (int cpt = 2 * (NB_ELEM / 5); cpt < 4 * (NB_ELEM / 5); cpt++) {
     snprintf(buf,1023, "%d", cpt);
     xbt_dynar_remove_at(d, 2 * (NB_ELEM / 5), &s2);
     xbt_test_assert(!strcmp(buf, s2), "Remove a bad value. Got %s, expected %s", s2, buf);