Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
change the prototype of s4u::Comm::wait_any to mimick the C code
authorMartin Quinson <martin.quinson@loria.fr>
Wed, 5 Jul 2017 23:18:41 +0000 (01:18 +0200)
committerMartin Quinson <martin.quinson@loria.fr>
Wed, 5 Jul 2017 23:18:45 +0000 (01:18 +0200)
Returning an iterator was not working as we returned every elements in
the input collection, without any sorting (fix #170).

Returning a collection or an iterator is difficult, as is. We would
have to build the collection in the backstage, iterating over the
provided comms to see which ones are done.

Plus, the user would probably want to then find these comms in the
provided vector to remove them from there.

In the end, that would be a lot of useless and potentially unefficient
code. It seems much better to provide the index in the vector provided
by the user. If she wants, she can iterate from there to see if the
comms are to be removed, or she can just remove this one and fire
another wait_any.

Maybe less C++ish, but more efficient and not that ugly either.

include/simgrid/s4u/Comm.hpp
teshsuite/s4u/comm-waitany/comm-waitany.cpp

index d409c0b..f577980 100644 (file)
@@ -11,6 +11,9 @@
 #include <simgrid/forward.h>
 #include <simgrid/s4u/Activity.hpp>
 #include <simgrid/s4u/forward.hpp>
+
+#include <vector>
+
 namespace simgrid {
 namespace s4u {
 /** @brief Communication async
@@ -28,19 +31,15 @@ public:
 
   /*! take a range of s4u::CommPtr (last excluded) and return when one of them is finished. The return value is an
    * iterator on the finished Comms. */
-  template <class I> static I wait_any(I first, I last)
-  {
-    return wait_any_for(first, last, -1);
-  }
+  static int wait_any(std::vector<CommPtr> * comms) { return wait_any_for(comms, -1); }
   /*! Same as wait_any, but with a timeout. If the timeout occurs, parameter last is returned.*/
-  template <class I> static I wait_any_for(I first, I last, double timeout)
+  static int wait_any_for(std::vector<CommPtr> * comms_in, double timeout)
   {
     // Map to dynar<Synchro*>:
     xbt_dynar_t comms = xbt_dynar_new(sizeof(simgrid::kernel::activity::ActivityImpl*), [](void*ptr){
       intrusive_ptr_release(*(simgrid::kernel::activity::ActivityImpl**)ptr);
     });
-    for (I iter = first; iter != last; iter++) {
-      CommPtr comm = *iter;
+    for (auto comm : *comms_in) {
       if (comm->state_ == inited)
         comm->start();
       xbt_assert(comm->state_ == started);
@@ -51,13 +50,7 @@ public:
     // Call the underlying simcall:
     int idx = simcall_comm_waitany(comms, timeout);
     xbt_dynar_free(&comms);
-    // Not found:
-    if (idx == -1)
-      return last;
-    // Lift the index to the corresponding iterator:
-    auto res       = std::next(first, idx);
-    (*res)->state_ = finished;
-    return res;
+    return idx;
   }
   /** Creates (but don't start) an async send to the mailbox @p dest */
   static CommPtr send_init(MailboxPtr dest);
index 75784b9..50303b1 100644 (file)
@@ -29,16 +29,10 @@ static void receiver()
     XBT_INFO("Sleeping for 3 seconds (for the %dth time)...", i + 1);
     simgrid::s4u::this_actor::sleep_for(3.0);
     XBT_INFO("Calling wait_any() for %zu pending comms", pending_comms.size());
-    std::vector<simgrid::s4u::CommPtr>::iterator ret_it =
-        simgrid::s4u::Comm::wait_any(pending_comms.begin(), pending_comms.end());
+    int changed_pos = simgrid::s4u::Comm::wait_any(&pending_comms);
     XBT_INFO("Counting the number of completed comms...");
 
-    int count = 0;
-    for (; ret_it != pending_comms.end(); count++, ret_it++)
-      ;
-
-    XBT_INFO("wait_any() replied that %d comms have completed", count);
-    // xbt_assert(count == 1, "wait_any() replied that %d comms have completed, which is broken!", count);
+    pending_comms.erase(pending_comms.begin() + changed_pos);
   }
 }