Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Avoid memcpy while retrieving data from dynars (speed up)
[simgrid.git] / src / xbt / dynar.c
index 8a65bc5..ca57b58 100644 (file)
@@ -8,14 +8,19 @@
 /* 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 "gras_private.h"
+#include "xbt/misc.h"
+#include "xbt/sysdep.h"
+#include "xbt/log.h"
+#include "xbt/error.h"
+#include "xbt/dynar.h"
+#include <sys/types.h>
 
-GRAS_LOG_NEW_DEFAULT_SUBCATEGORY(dynar,tbx);
+GRAS_LOG_NEW_DEFAULT_SUBCATEGORY(dynar,xbt,"Dynamic arrays");
 
 struct gras_dynar_s {
-  size_t          size;
-  size_t          used;
-  size_t          elmsize;
+  unsigned long          size;
+  unsigned long          used;
+  unsigned long          elmsize;
   void           *data;
   void_f_pvoid_t *free;
 };
@@ -26,55 +31,51 @@ struct gras_dynar_s {
 #define __sanity_check_idx(idx)                \
            gras_assert1(idx >= 0,             \
                        "dynar idx(=%d) < 0", \
-                       idx)
+                       (int) (idx))
 #define __check_inbound_idx(dynar, idx)                                                \
            gras_assert2(idx < dynar->used,                                             \
-                       "dynar is not that long. You asked %d, but it's only %d long", \
-                       idx, dynar->used)
+                       "dynar is not that long. You asked %d, but it's only %lu long", \
+                       (int) (idx), (unsigned long) dynar->used)
 #define __check_sloppy_inbound_idx(dynar, idx)                                         \
            gras_assert2(idx <= dynar->used,                                            \
-                       "dynar is not that long. You asked %d, but it's only %d long", \
-                       idx, dynar->used)
+                       "dynar is not that long. You asked %d, but it's only %lu long", \
+                       (int) (idx), (unsigned long) dynar->used)
 #define __check_populated_dynar(dynar)            \
-           gras_assert0(dynar->used,              \
-                       "dynar contains nothing")
+           gras_assert1(dynar->used,              \
+                       "dynar %p contains nothing",(void*)dynar)
 
-
-static inline
-void
-_gras_clear_mem(void * const ptr,
-                const size_t length) {
+static _GRAS_INLINE 
+void _gras_clear_mem(void * const ptr,
+                    const unsigned long length) {
   memset(ptr, 0, length);
 }
 
-static inline
+static _GRAS_INLINE
 gras_error_t
 _gras_dynar_expand(gras_dynar_t * const dynar,
                    const int            nb) {
   gras_error_t errcode     = no_error;
-  const size_t old_size    = dynar->size;
+  const unsigned long old_size    = dynar->size;
 
   if (nb > old_size) {
     char * const old_data    = dynar->data;
 
-    const size_t elmsize     = dynar->elmsize;
-    const size_t old_length  = old_size*elmsize;
+    const unsigned long elmsize     = dynar->elmsize;
+    const unsigned long old_length  = old_size*elmsize;
 
-    const size_t used        = dynar->used;
-    const size_t used_length = used*elmsize;
+    const unsigned long used        = dynar->used;
+    const unsigned long used_length = used*elmsize;
 
-    const size_t new_size    = nb > (2*(old_size+1)) ? nb : (2*(old_size+1));
-    const size_t new_length  = new_size*elmsize;
-    char * const new_data    = calloc(1, elmsize*new_size);
+    const unsigned long new_size    = nb > (2*(old_size+1)) ? nb : (2*(old_size+1));
+    const unsigned long new_length  = new_size*elmsize;
+    char * const new_data    = gras_malloc0(elmsize*new_size);
 
-    DEBUG3("expend %p from %d to %d elements", dynar, old_size, nb);
-    if (!new_data)
-      RAISE_MALLOC;
+    DEBUG3("expend %p from %lu to %d elements", (void*)dynar, (unsigned long)old_size, nb);
 
     if (old_data) {
       memcpy(new_data, old_data, used_length);
       _gras_clear_mem(old_data, old_length);
-      free(old_data);
+      gras_free(old_data);
     }
 
     _gras_clear_mem(new_data + used_length, new_length - used_length);
@@ -86,58 +87,52 @@ _gras_dynar_expand(gras_dynar_t * const dynar,
   return errcode;
 }
 
-static inline
+static _GRAS_INLINE
 void *
 _gras_dynar_elm(const gras_dynar_t * const dynar,
-                const size_t               idx) {
+                  const unsigned long        idx) {
   char * const data    = dynar->data;
-  const size_t elmsize = dynar->elmsize;
+  const unsigned long elmsize = dynar->elmsize;
 
   return data + idx*elmsize;
 }
 
-static inline
+static _GRAS_INLINE
 void
 _gras_dynar_get_elm(void               * const dst,
                     const gras_dynar_t * const dynar,
-                    const size_t               idx) {
+                    const unsigned long               idx) {
   void * const elm     = _gras_dynar_elm(dynar, idx);
-  const size_t elmsize = dynar->elmsize;
+  const unsigned long elmsize = dynar->elmsize;
 
   memcpy(dst, elm, elmsize);
 }
 
-static inline
+static _GRAS_INLINE
 void
 _gras_dynar_put_elm(const gras_dynar_t * const dynar,
-                    const size_t               idx,
+                    const unsigned long               idx,
                     const void         * const src) {
   void * const elm     = _gras_dynar_elm(dynar, idx);
-  const size_t elmsize = dynar->elmsize;
+  const unsigned long elmsize = dynar->elmsize;
 
   memcpy(elm, src, elmsize);
 }
 
 /**
  * gras_dynar_new:
- * @whereto: pointer to where the dynar should be created
  * @elm_size: size of each element in the dynar
  * @free_func: function to call each time we want to get rid of an element (or NULL if nothing to do).
- * @Returns: malloc_error or no_error
  *
  * 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 **).
  */
-gras_error_t
-gras_dynar_new(gras_dynar_t   ** const p_dynar,
-               const size_t            elmsize,
-               void_f_pvoid_t  * const free_func) {
-  gras_error_t  errcode = no_error;
-  gras_dynar_t *dynar   = NULL;
-
-  if (!(dynar = calloc(1, sizeof(gras_dynar_t))))
-    RAISE_MALLOC;
+gras_dynar_t *
+gras_dynar_new(const unsigned long           elmsize,
+               void_f_pvoid_t * const free_func) {
+   
+  gras_dynar_t *dynar = gras_new0(gras_dynar_t,1);
 
   dynar->size    = 0;
   dynar->used    = 0;
@@ -145,9 +140,7 @@ gras_dynar_new(gras_dynar_t   ** const p_dynar,
   dynar->data    = NULL;
   dynar->free    = free_func;
 
-  *p_dynar = dynar;
-
-  return errcode;
+  return dynar;
 }
 
 /**
@@ -163,12 +156,12 @@ gras_dynar_free_container(gras_dynar_t * const dynar) {
 
     if (dynar->data) {
       _gras_clear_mem(dynar->data, dynar->size);
-      free(dynar->data);
+      gras_free(dynar->data);
     }
 
     _gras_clear_mem(dynar, sizeof(gras_dynar_t));
 
-    free(dynar);
+    gras_free(dynar);
   }
 }
 
@@ -183,13 +176,14 @@ gras_dynar_reset(gras_dynar_t * const dynar) {
 
   __sanity_check_dynar(dynar);
 
+  DEBUG1("Reset the dynar %p",(void*)dynar);
   if (dynar->free) {
     gras_dynar_map(dynar, dynar->free);
   }
 
   if (dynar->data) {
     _gras_clear_mem(dynar->data, dynar->size);
-    free(dynar->data);
+    gras_free(dynar->data);
   }
 
   dynar->size = 0;
@@ -218,9 +212,29 @@ gras_dynar_free(gras_dynar_t * const dynar) {
  *
  * Returns the count of elements in a dynar
  */
-size_t
+unsigned long
 gras_dynar_length(const gras_dynar_t * const dynar) {
-  return (dynar ? dynar->used : (size_t)0);
+  return (dynar ? (unsigned long) dynar->used : (unsigned long)0);
+}
+
+/**
+ * gras_dynar_get_cpy:
+ * @dynar: information dealer
+ * @idx: index of the slot we want to retrive
+ * @dst: where to pu the result to.
+ *
+ * Retrieve a copy of the Nth element of a dynar.
+ */
+void
+gras_dynar_get_cpy(const gras_dynar_t * const dynar,
+                  const int                  idx,
+                  void               * const dst) {
+
+  __sanity_check_dynar(dynar);
+  __sanity_check_idx(idx);
+  __check_inbound_idx(dynar, idx);
+
+  _gras_dynar_get_elm(dst, dynar, idx);
 }
 
 /**
@@ -232,16 +246,15 @@ gras_dynar_length(const gras_dynar_t * const dynar) {
  * Retrieve the Nth element of a dynar. Warning, the returned value is the actual content of 
  * the dynar. Make a copy before fooling with it.
  */
-void
-gras_dynar_get(const gras_dynar_t * const dynar,
-               const int                  idx,
-               void               * const dst) {
+void*
+gras_dynar_get_ptr(const gras_dynar_t * const dynar,
+                  const int                  idx) {
 
   __sanity_check_dynar(dynar);
   __sanity_check_idx(idx);
   __check_inbound_idx(dynar, idx);
 
-  _gras_dynar_get_elm(dst, dynar, idx);
+  return _gras_dynar_elm(dynar, idx);
 }
 
 /**
@@ -249,30 +262,26 @@ gras_dynar_get(const gras_dynar_t * const dynar,
  * @dynar:
  * @idx:
  * @src: What will be feeded to the dynar
- * @Returns: malloc_error or no_error
  *
  * Set the Nth element of a dynar, expanding the dynar if needed, BUT NOT freeing
  * the previous value at this position. If you want to free the previous content,
  * use gras_dynar_remplace().
  */
-gras_error_t
+void
 gras_dynar_set(gras_dynar_t * const dynar,
                const int            idx,
                const void   * const src) {
-  gras_error_t errcode = no_error;
 
   __sanity_check_dynar(dynar);
   __sanity_check_idx(idx);
 
-  TRY(_gras_dynar_expand(dynar, idx+1));
+  _gras_dynar_expand(dynar, idx+1);
 
   if (idx >= dynar->used) {
     dynar->used = idx+1;
   }
 
   _gras_dynar_put_elm(dynar, idx, src);
-
-  return errcode;
 }
 
 /**
@@ -280,17 +289,15 @@ gras_dynar_set(gras_dynar_t * const dynar,
  * @dynar:
  * @idx:
  * @object:
- * @Returns: malloc_error or no_error
  *
  * Set the Nth element of a dynar, expanding the dynar if needed, AND DO
  * free the previous value at this position. If you don't want to free the
  * previous content, use gras_dynar_set().
  */
-gras_error_t
+void
 gras_dynar_remplace(gras_dynar_t * const dynar,
                     const int            idx,
                     const void   * const object) {
-  gras_error_t errcode = no_error;
 
   __sanity_check_dynar(dynar);
   __sanity_check_idx(idx);
@@ -301,9 +308,7 @@ gras_dynar_remplace(gras_dynar_t * const dynar,
     dynar->free(old_object);
   }
 
-  errcode = gras_dynar_set(dynar, idx, object);
-
-  return errcode;
+  gras_dynar_set(dynar, idx, object);
 }
 
 /**
@@ -311,33 +316,31 @@ gras_dynar_remplace(gras_dynar_t * const dynar,
  * @dynar:
  * @idx:
  * @src: What will be feeded to the dynar
- * @Returns: malloc_error or no_error
  *
  * Set the Nth element of a dynar, expanding the dynar if needed, and
  * moving the previously existing value and all subsequent ones to one
  * position right in the dynar.
  */
-gras_error_t
+void
 gras_dynar_insert_at(gras_dynar_t * const dynar,
                      const int            idx,
                      const void   * const src) {
-  gras_error_t errcode = no_error;
 
   __sanity_check_dynar(dynar);
   __sanity_check_idx(idx);
   __check_sloppy_inbound_idx(dynar, idx);
 
   {
-    const size_t old_used = dynar->used;
-    const size_t new_used = old_used + 1;
+    const unsigned long old_used = dynar->used;
+    const unsigned long new_used = old_used + 1;
 
-    TRY(_gras_dynar_expand(dynar, new_used));
+    _gras_dynar_expand(dynar, new_used);
 
     {
-      const size_t nb_shift =  old_used - idx;
-      const size_t elmsize  =  dynar->elmsize;
+      const unsigned long nb_shift =  old_used - idx;
+      const unsigned long elmsize  =  dynar->elmsize;
 
-      const size_t offset   =  nb_shift*elmsize;
+      const unsigned long offset   =  nb_shift*elmsize;
 
       void * const elm_src  = _gras_dynar_elm(dynar, idx);
       void * const elm_dst  = _gras_dynar_elm(dynar, idx+1);
@@ -348,8 +351,6 @@ gras_dynar_insert_at(gras_dynar_t * const dynar,
     _gras_dynar_put_elm(dynar, idx, src);
     dynar->used = new_used;
   }
-
-  return errcode;
 }
 
 /**
@@ -374,13 +375,13 @@ gras_dynar_remove_at(gras_dynar_t * const dynar,
     _gras_dynar_get_elm(object, dynar, idx);
 
   {
-    const size_t old_used = dynar->used;
-    const size_t new_used = old_used - 1;
+    const unsigned long old_used = dynar->used;
+    const unsigned long new_used = old_used - 1;
 
-    const size_t nb_shift =  old_used-1 - idx;
-    const size_t elmsize  =  dynar->elmsize;
+    const unsigned long nb_shift =  old_used-1 - idx;
+    const unsigned long elmsize  =  dynar->elmsize;
 
-    const size_t offset   =  nb_shift*elmsize;
+    const unsigned long offset   =  nb_shift*elmsize;
 
     void * const elm_src  = _gras_dynar_elm(dynar, idx+1);
     void * const elm_dst  = _gras_dynar_elm(dynar, idx);
@@ -395,15 +396,14 @@ gras_dynar_remove_at(gras_dynar_t * const dynar,
  * gras_dynar_push:
  * @dynar:
  * @src:
- * @Returns: malloc_error or no_error
  *
  * Add an element at the end of the dynar
  */
-gras_error_t
+void
 gras_dynar_push(gras_dynar_t * const dynar,
                 const void   * const src) {
   __sanity_check_dynar(dynar);
-  return gras_dynar_insert_at(dynar, dynar->used, src);
+  gras_dynar_insert_at(dynar, dynar->used, src);
 }
 
 /**
@@ -418,6 +418,7 @@ gras_dynar_pop(gras_dynar_t * const dynar,
                void         * const dst) {
   __sanity_check_dynar(dynar);
   __check_populated_dynar(dynar);
+  DEBUG1("Pop %p",(void*)dynar);
   gras_dynar_remove_at(dynar, dynar->used-1, dst);
 }
 
@@ -425,16 +426,15 @@ gras_dynar_pop(gras_dynar_t * const dynar,
  * gras_dynar_unshift:
  * @dynar:
  * @src:
- * @Returns: malloc_error or no_error
  *
  * Add an element at the begining of the dynar (rather long, Use
  * gras_dynar_push() when possible)
  */
-gras_error_t
+void
 gras_dynar_unshift(gras_dynar_t * const dynar,
                    const void   * const src) {
   __sanity_check_dynar(dynar);
-  return gras_dynar_insert_at(dynar, 0, src);
+  gras_dynar_insert_at(dynar, 0, src);
 }
 
 /**
@@ -470,8 +470,8 @@ gras_dynar_map(const gras_dynar_t * const dynar,
 
   {
     char         elm[64];
-    const size_t used = dynar->used;
-    size_t       i    = 0;
+    const unsigned long used = dynar->used;
+    unsigned long       i    = 0;
 
     for (i = 0; i < used; i++) {
       _gras_dynar_get_elm(elm, dynar, i);
@@ -496,7 +496,7 @@ gras_dynar_cursor_first(const gras_dynar_t * const dynar,
                        int                * const cursor) {
 
   __sanity_check_dynar(dynar);
-  DEBUG1("Set cursor on %p to the first position",dynar);
+  DEBUG1("Set cursor on %p to the first position",(void*)dynar);
   *cursor = 0;
 }
 
@@ -529,10 +529,10 @@ gras_dynar_cursor_get(const gras_dynar_t * const dynar,
     const int idx = *cursor;
 
     if (idx >= dynar->used) {
-      DEBUG1("Cursor on %p already on last elem",dynar);
+      DEBUG1("Cursor on %p already on last elem",(void*)dynar);
       return FALSE;
     }
-    DEBUG2("Cash out cursor on %p at %d",dynar,idx);
+    DEBUG2("Cash out cursor on %p at %d",(void*)dynar,idx);
 
     _gras_dynar_get_elm(dst, dynar, idx);
   }
@@ -551,7 +551,21 @@ void gras_dynar_cursor_rm(gras_dynar_t * dynar,
                          int          * const cursor) {
   void *dst;
 
-  gras_dynar_remove_at(dynar,(*cursor)--,&dst);
-  if (dynar->free)
-    (dynar->free)(dst);
+  if (dynar->elmsize > sizeof(void*)) {
+    DEBUG0("Elements too big to fit into a pointer");
+    if (dynar->free) {
+      dst=gras_malloc(dynar->elmsize);
+      gras_dynar_remove_at(dynar,(*cursor)--,dst);
+      (dynar->free)(dst);
+      gras_free(dst);
+    } else {
+      DEBUG0("Ok, we dont care about the element when no free function");
+      gras_dynar_remove_at(dynar,(*cursor)--,NULL);
+    }
+      
+  } else {
+    gras_dynar_remove_at(dynar,(*cursor)--,&dst);
+    if (dynar->free)
+      (dynar->free)(dst);
+  }
 }