Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
8691b45ad2f7a7a5845be2cd9ae43e85b042fdb0
[simgrid.git] / examples / cpp / comm-serialize / s4u-comm-serialize.cpp
1 /* Copyright (c) 2010-2021. The SimGrid Team. All rights reserved.          */
2
3 /* This program is free software; you can redistribute it and/or modify it
4  * under the terms of the license (GNU LGPL) which comes with this package. */
5
6 /* This example shows how to serialize a set of communications going through a link
7  *
8  * As for the other asynchronous examples, the sender initiates all the messages it wants to send and
9  * pack the resulting simgrid::s4u::CommPtr objects in a vector.
10  * At the same time, the receiver starts receiving all messages asynchronously. Without serialization,
11  * all messages would be received at the same timestamp in the receiver.
12  *
13  * However, as they will be serialized in a link of the platform, the messages arrive 2 by 2.
14  *
15  * The sender then blocks until all ongoing communication terminate, using simgrid::s4u::Comm::wait_all()
16  */
17
18 #include "simgrid/s4u.hpp"
19 #include <string>
20 namespace sg4 = simgrid::s4u;
21
22 XBT_LOG_NEW_DEFAULT_CATEGORY(s4u_async_serialize, "Messages specific for this s4u example");
23
24 class Sender {
25   int messages_count; /* - number of messages */
26   int msg_size;       /* - message size in bytes */
27
28 public:
29   explicit Sender(int size, int count) : messages_count(count), msg_size(size) {}
30   void operator()() const
31   {
32     // sphinx-doc: init-begin (this line helps the doc to build; ignore it)
33     /* Vector in which we store all ongoing communications */
34     std::vector<sg4::CommPtr> pending_comms;
35
36     /* Make a vector of the mailboxes to use */
37     sg4::Mailbox* mbox = sg4::Mailbox::by_name("receiver");
38     // sphinx-doc: init-end
39
40     /* Start dispatching all messages to receiver */
41     for (int i = 0; i < messages_count; i++) {
42       std::string msg_content = std::string("Message ") + std::to_string(i);
43       // Copy the data we send: the 'msg_content' variable is not a stable storage location.
44       // It will be destroyed when this actor leaves the loop, ie before the receiver gets it
45       auto* payload = new std::string(msg_content);
46
47       XBT_INFO("Send '%s' to '%s'", msg_content.c_str(), mbox->get_cname());
48
49       /* Create a communication representing the ongoing communication, and store it in pending_comms */
50       sg4::CommPtr comm = mbox->put_async(payload, msg_size);
51       pending_comms.push_back(comm);
52     }
53
54     XBT_INFO("Done dispatching all messages");
55
56     /* Now that all message exchanges were initiated, wait for their completion in one single call */
57     sg4::Comm::wait_all(pending_comms);
58     // sphinx-doc: put-end
59
60     XBT_INFO("Goodbye now!");
61   }
62 };
63
64 /* Receiver actor expects 1 argument: number of messages to be received */
65 class Receiver {
66   sg4::Mailbox* mbox;
67   int messages_count = 10; /* - number of messages */
68
69 public:
70   explicit Receiver(int count) : messages_count(count) { mbox = sg4::Mailbox::by_name("receiver"); }
71   void operator()()
72   {
73     /* Vector in which we store all incoming msgs */
74     std::vector<std::unique_ptr<std::string*>> pending_msgs;
75     std::vector<sg4::CommPtr> pending_comms;
76
77     XBT_INFO("Wait for %d messages asynchronously", messages_count);
78     for (int i = 0; i < messages_count; i++) {
79       pending_msgs.push_back(std::make_unique<std::string*>());
80       pending_comms.emplace_back(mbox->get_async<std::string>(pending_msgs[i].get()));
81     }
82     while (not pending_comms.empty()) {
83       ssize_t index    = sg4::Comm::wait_any(pending_comms);
84       std::string* msg = *pending_msgs[index];
85       XBT_INFO("I got '%s'.", msg->c_str());
86       /* cleanup memory and remove from vectors */
87       delete msg;
88       pending_comms.erase(pending_comms.begin() + index);
89       pending_msgs.erase(pending_msgs.begin() + index);
90     }
91   }
92 };
93
94 int main(int argc, char* argv[])
95 {
96   sg4::Engine e(&argc, argv);
97   /* Creates the platform
98    *  ________                 __________
99    * | Sender |===============| Receiver |
100    * |________|    Link1      |__________|
101    */
102   auto* zone     = sg4::create_full_zone("Zone1");
103   auto* sender   = zone->create_host("sender", 1)->seal();
104   auto* receiver = zone->create_host("receiver", 1)->seal();
105
106   /* create split-duplex link1 (UP/DOWN), limiting the number of concurrent flows in it for 2 */
107   const auto* link =
108       zone->create_split_duplex_link("link1", 10e9)->set_latency(10e-6)->set_concurrency_limit(2)->seal();
109
110   /* create routes between nodes */
111   zone->add_route(sender->get_netpoint(), receiver->get_netpoint(), nullptr, nullptr,
112                   {{link, sg4::LinkInRoute::Direction::UP}}, true);
113   zone->seal();
114
115   /* create actors Sender/Receiver */
116   sg4::Actor::create("receiver", receiver, Receiver(10));
117   sg4::Actor::create("sender", sender, Sender(1e6, 10));
118
119   e.run();
120
121   return 0;
122 }