Logo AND Algorithmique Numérique Distribuée

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