1 /* Copyright (c) 2010-2023. The SimGrid Team. All rights reserved. */
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. */
6 /* This example shows how to serialize a set of communications going through a link using Link::set_concurrency_limit()
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.
14 #include "simgrid/s4u.hpp"
16 namespace sg4 = simgrid::s4u;
18 XBT_LOG_NEW_DEFAULT_CATEGORY(s4u_async_serialize, "Messages specific for this s4u example");
21 int messages_count; /* - number of messages */
22 int msg_size; /* - message size in bytes */
25 explicit Sender(int size, int count) : messages_count(count), msg_size(size) {}
26 void operator()() const
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;
33 sg4::Mailbox* mbox = sg4::Mailbox::by_name("receiver");
34 // sphinx-doc: init-end
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);
43 XBT_INFO("Send '%s' to '%s'", msg_content.c_str(), mbox->get_cname());
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);
50 XBT_INFO("Done dispatching all messages");
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
56 XBT_INFO("Goodbye now!");
60 /* Receiver actor expects 1 argument: number of messages to be received */
63 int messages_count = 10; /* - number of messages */
66 explicit Receiver(int count) : messages_count(count) { mbox = sg4::Mailbox::by_name("receiver"); }
69 /* Where we store all incoming msgs */
70 std::unordered_map<sg4::CommPtr, std::shared_ptr<std::string*>> pending_msgs;
71 sg4::ActivitySet pending_comms;
73 XBT_INFO("Wait for %d messages asynchronously", messages_count);
74 for (int i = 0; i < messages_count; i++) {
75 std::shared_ptr<std::string*> msg =std::make_shared<std::string*>();
76 auto comm = mbox->get_async<std::string>(msg.get());
77 pending_comms.push(comm);
78 pending_msgs.insert({comm, msg});
81 while (not pending_comms.empty()) {
82 auto completed_one = pending_comms.wait_any();
83 if (completed_one != nullptr){
84 auto comm = boost::dynamic_pointer_cast<sg4::Comm>(completed_one);
85 auto msg = *pending_msgs[comm];
86 XBT_INFO("I got '%s'.", msg->c_str());
87 /* cleanup memory and remove from map */
89 pending_msgs.erase(comm);
95 int main(int argc, char* argv[])
97 sg4::Engine e(&argc, argv);
98 /* Creates the platform
100 * | Sender |===============| Receiver |
101 * |________| Link1 |__________|
103 auto* zone = sg4::create_full_zone("Zone1");
104 auto* sender = zone->create_host("sender", 1)->seal();
105 auto* receiver = zone->create_host("receiver", 1)->seal();
107 /* create split-duplex link1 (UP/DOWN), limiting the number of concurrent flows in it for 2 */
109 zone->create_split_duplex_link("link1", 10e9)->set_latency(10e-6)->set_concurrency_limit(2)->seal();
111 /* create routes between nodes */
112 zone->add_route(sender, receiver, {link});
115 /* create actors Sender/Receiver */
116 sg4::Actor::create("receiver", receiver, Receiver(10));
117 sg4::Actor::create("sender", sender, Sender(1e6, 10));