Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Add a function to merge 2 dynar to avoid xbt_dynar_push in a loop
[simgrid.git] / src / xbt / dynar.c
index 437a47f..0574b41 100644 (file)
@@ -6,7 +6,6 @@
 /* This program is free software; you can redistribute it and/or modify it
  * under the terms of the license (GNU LGPL) which comes with this package. */
 
-#include "portable.h"           /* SIZEOF_MAX */
 #include "xbt/misc.h"
 #include "xbt/sysdep.h"
 #include "xbt/log.h"
@@ -74,12 +73,6 @@ static XBT_INLINE void _check_populated_dynar(xbt_dynar_t dynar)
 
 static void _dynar_map(const xbt_dynar_t dynar, void_f_pvoid_t const op);
 
-static XBT_INLINE
-    void _xbt_clear_mem(void *const ptr, const unsigned long length)
-{
-  memset(ptr, 0, length);
-}
-
 static XBT_INLINE
 void _xbt_dynar_resize(xbt_dynar_t dynar, unsigned long new_size)
 {
@@ -147,16 +140,7 @@ _xbt_dynar_remove_at(xbt_dynar_t const dynar,
   if (object) {
     _xbt_dynar_get_elm(object, dynar, idx);
   } else if (dynar->free_f) {
-    if (dynar->elmsize <= SIZEOF_MAX) {
-      char elm[SIZEOF_MAX];
-      _xbt_dynar_get_elm(elm, dynar, idx);
-      dynar->free_f(elm);
-    } else {
-      char *elm = malloc(dynar->elmsize);
-      _xbt_dynar_get_elm(elm, dynar, idx);
-      dynar->free_f(elm);
-      free(elm);
-    }
+    dynar->free_f(_xbt_dynar_elm(dynar, idx));
   }
 
   nb_shift = dynar->used - 1 - idx;
@@ -254,6 +238,28 @@ XBT_INLINE void xbt_dynar_reset(xbt_dynar_t const dynar)
   _dynar_unlock(dynar);
 }
 
+/** @brief Merge dynar d2 into d1
+ *
+ * \param d1 dynar to keep
+ * \param d2 dynar to merge into d1. This dynar is free at end.
+ */
+void xbt_dynar_merge(xbt_dynar_t *d1, xbt_dynar_t *d2)
+{
+  if((*d1)->elmsize != (*d2)->elmsize)
+    xbt_die("Element size must are not equal");
+
+  const unsigned long elmsize = (*d1)->elmsize;
+
+  void *ptr = _xbt_dynar_elm((*d2), 0);
+  _xbt_dynar_resize(*d1, (*d1)->size + (*d2)->size);
+  void *elm = _xbt_dynar_elm((*d1), (*d1)->used);
+
+  memcpy(elm, ptr, ((*d2)->size)*elmsize);
+  (*d1)->used += (*d2)->used;
+  (*d2)->used = 0;
+  xbt_dynar_free(d2);
+}
+
 /**
  * \brief Shrink the dynar by removing empty slots at the end of the internal array
  * \param dynar a dynar
@@ -307,7 +313,7 @@ XBT_INLINE unsigned long xbt_dynar_length(const xbt_dynar_t dynar)
   return (dynar ? (unsigned long) dynar->used : (unsigned long) 0);
 }
 
-/**@brief check if a dynar is empty
+ /**@brief check if a dynar is empty
  *
  *\param dynar the dynat we want to check
  */
@@ -366,8 +372,10 @@ static XBT_INLINE void *_xbt_dynar_set_at_ptr(const xbt_dynar_t dynar,
 
   if (idx >= dynar->used) {
     _xbt_dynar_expand(dynar, idx + 1);
-    _xbt_clear_mem(((char * const)dynar->data) + dynar->used * dynar->elmsize,
-                   (idx + 1 - dynar->used)*dynar->elmsize);
+    if (idx > dynar->used) {
+      memset(_xbt_dynar_elm(dynar, dynar->used), 0,
+             (idx - dynar->used) * dynar->elmsize);
+    }
     dynar->used = idx + 1;
   }
   return _xbt_dynar_elm(dynar, idx);
@@ -718,13 +726,14 @@ XBT_INLINE void xbt_dynar_sort(xbt_dynar_t dynar,
  */
 XBT_INLINE void * xbt_dynar_to_array (xbt_dynar_t dynar)
 {
-  void * res;
-       void * last = xbt_new0(char,dynar->elmsize);
-       xbt_dynar_push(dynar, last);
-       free(last);
-       res = dynar->data;
-       free(dynar);
-       return res;
+  void *res;
+  xbt_dynar_shrink(dynar, 1);
+  memset(xbt_dynar_push_ptr(dynar), 0, dynar->elmsize);
+  res = dynar->data;
+  if (dynar->mutex)
+    xbt_mutex_destroy(dynar->mutex);
+  free(dynar);
+  return res;
 }
 
 /*
@@ -744,13 +753,13 @@ XBT_INLINE int xbt_dynar_compare(xbt_dynar_t d1, xbt_dynar_t d2,
        }
        if((d1->elmsize)!=(d2->elmsize))
        {
-               XBT_DEBUG("Size of elmsize d1=%ld d2=%ld",d1->elmsize,d2->elmsize);
+               XBT_DEBUG("Size of elmsize d1=%lu d2=%lu",d1->elmsize,d2->elmsize);
                xbt_dynar_free(&d2);
                return 1; // xbt_die
        }
        if(xbt_dynar_length(d1) != xbt_dynar_length(d2))
        {
-               XBT_DEBUG("Size of dynar d1=%ld d2=%ld",xbt_dynar_length(d1),xbt_dynar_length(d2));
+               XBT_DEBUG("Size of dynar d1=%lu d2=%lu",xbt_dynar_length(d1),xbt_dynar_length(d2));
                xbt_dynar_free(&d2);
                return 1;
        }
@@ -811,14 +820,14 @@ XBT_TEST_UNIT("int", test_dynar_int, "Dynars of integers")
   for (cursor = 0; cursor < NB_ELEM; cursor++) {
     iptr = xbt_dynar_get_ptr(d, cursor);
     xbt_test_assert(cursor == *iptr,
-                     "The retrieved value is not the same than the injected one (%d!=%d)",
+                     "The retrieved value is not the same than the injected one (%u!=%d)",
                      cursor, cpt);
   }
 
   /* 3. Traverse the dynar using the neat macro to that extend */
   xbt_dynar_foreach(d, cursor, cpt) {
     xbt_test_assert(cursor == cpt,
-                     "The retrieved value is not the same than the injected one (%d!=%d)",
+                     "The retrieved value is not the same than the injected one (%u!=%d)",
                      cursor, cpt);
   }
   /* end_of_traversal */
@@ -950,7 +959,7 @@ XBT_TEST_UNIT("insert",test_dynar_insert,"Using the xbt_dynar_insert and xbt_dyn
   /* 3. Traverse the dynar */
   xbt_dynar_foreach(d, cursor, cpt) {
     xbt_test_assert(cursor == cpt,
-                     "The retrieved value is not the same than the injected one (%d!=%d)",
+                     "The retrieved value is not the same than the injected one (%u!=%d)",
                      cursor, cpt);
   }
   /* end_of_traversal */
@@ -960,14 +969,14 @@ XBT_TEST_UNIT("insert",test_dynar_insert,"Using the xbt_dynar_insert and xbt_dyn
     xbt_dynar_set_as(d, cpt, int, cpt);
   xbt_dynar_foreach(d, cursor, cpt)
     xbt_test_assert(cursor == cpt,
-                     "The retrieved value is not the same than the injected one (%d!=%d)",
+                     "The retrieved value is not the same than the injected one (%u!=%d)",
                      cursor, cpt);
 
   for (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 (%d!=%d)",
+                     "The retrieved value is not the same than the injected one (%u!=%d)",
                      cursor, cpt);
   }
   xbt_test_assert(xbt_dynar_is_empty(d),
@@ -986,7 +995,7 @@ XBT_TEST_UNIT("insert",test_dynar_insert,"Using the xbt_dynar_insert and xbt_dyn
   /* 3. Traverse the dynar */
   xbt_dynar_foreach(d, cursor, cpt) {
     xbt_test_assert(cursor == cpt,
-                     "The retrieved value is not the same than the injected one (%d!=%d)",
+                     "The retrieved value is not the same than the injected one (%u!=%d)",
                      cursor, cpt);
   }
   /* end_of_traversal */
@@ -995,7 +1004,7 @@ XBT_TEST_UNIT("insert",test_dynar_insert,"Using the xbt_dynar_insert and xbt_dyn
     int val;
     xbt_dynar_remove_at(d,xbt_dynar_length(d)-1,&val);
     xbt_test_assert(cpt == val,
-                     "The retrieved value is not the same than the injected one (%d!=%d)",
+                     "The retrieved value is not the same than the injected one (%u!=%d)",
                      cursor, cpt);
   }
   xbt_test_assert(xbt_dynar_is_empty(d),
@@ -1192,7 +1201,7 @@ XBT_TEST_UNIT("string", test_dynar_string, "Dynars of strings")
   }
   /* 2. Traverse the dynar with the macro */
   xbt_dynar_foreach(d, iter, s1) {
-    sprintf(buf, "%d", NB_ELEM - iter - 1);
+    sprintf(buf, "%u", NB_ELEM - iter - 1);
     xbt_test_assert(!strcmp(buf, s1),
                      "The retrieved value is not the same than the injected one (%s!=%s)",
                      buf, s1);