1 /* Copyright (c) 2010-2020. 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 #include "simgrid/actor.h"
7 #include "simgrid/comm.h"
8 #include "simgrid/engine.h"
9 #include "simgrid/forward.h"
10 #include "simgrid/mailbox.h"
11 #include "xbt/asserts.h"
15 #include <stdio.h> /* snprintf */
17 XBT_LOG_NEW_DEFAULT_CATEGORY(async_waitany, "Messages specific for this example");
19 static void sender(int argc, char* argv[])
21 xbt_assert(argc == 4, "Expecting 3 parameters from the XML deployment file but got %d", argc);
22 long messages_count = xbt_str_parse_int(argv[1], "Invalid amount of tasks: %s");
23 long msg_size = xbt_str_parse_int(argv[2], "Invalid communication size: %s");
24 long receivers_count = xbt_str_parse_int(argv[3], "Invalid amount of receivers: %s");
26 /* Array in which we store all ongoing communications */
27 sg_comm_t* pending_comms = malloc(sizeof(sg_comm_t) * (messages_count + receivers_count));
28 int pending_comms_count = 0;
30 /* Make an array of the mailboxes to use */
31 sg_mailbox_t* mboxes = malloc(sizeof(sg_mailbox_t) * receivers_count);
32 for (long i = 0; i < receivers_count; i++) {
33 char mailbox_name[80];
34 snprintf(mailbox_name, 79, "receiver-%ld", i);
35 sg_mailbox_t mbox = sg_mailbox_by_name(mailbox_name);
39 /* Start dispatching all messages to receivers, in a round robin fashion */
40 for (int i = 0; i < messages_count; i++) {
42 snprintf(msg_content, 79, "Message %d", i);
43 sg_mailbox_t mbox = mboxes[i % receivers_count];
44 XBT_INFO("Send '%s' to '%s'", msg_content, sg_mailbox_get_name(mbox));
46 /* Create a communication representing the ongoing communication, and store it in pending_comms */
47 pending_comms[pending_comms_count++] = sg_mailbox_put_async(mbox, xbt_strdup(msg_content), msg_size);
49 /* Start sending messages to let the workers know that they should stop */
50 for (int i = 0; i < receivers_count; i++) {
51 XBT_INFO("Send 'finalize' to 'receiver-%d'", i);
52 char* end_msg = xbt_strdup("finalize");
53 sg_mailbox_t mbox = mboxes[i % receivers_count];
54 pending_comms[pending_comms_count++] = sg_mailbox_put_async(mbox, end_msg, 0);
57 XBT_INFO("Done dispatching all messages");
59 /* Now that all message exchanges were initiated, wait for their completion, in order of termination.
61 * This loop waits for first terminating message with wait_any() and remove it from the array (with a memmove),
62 * until all comms are terminated.
63 * Even in this simple example, the pending comms do not terminate in the exact same order of creation.
65 while (pending_comms_count != 0) {
66 int changed_pos = sg_comm_wait_any(pending_comms, pending_comms_count);
67 memmove(pending_comms + changed_pos, pending_comms + changed_pos + 1,
68 sizeof(sg_comm_t) * (pending_comms_count - changed_pos - 1));
69 pending_comms_count--;
72 XBT_INFO("Remove the %dth pending comm: it terminated earlier than another comm that was initiated first.",
79 XBT_INFO("Goodbye now!");
82 static void receiver(int argc, char* argv[])
84 xbt_assert(argc == 2, "Expecting one parameter from the XML deployment file but got %d", argc);
85 int id = xbt_str_parse_int(argv[1], "ID should be numerical, not %s");
86 char mailbox_name[80];
87 snprintf(mailbox_name, 79, "receiver-%d", id);
88 sg_mailbox_t mbox = sg_mailbox_by_name(mailbox_name);
89 XBT_INFO("Wait for my first message on '%s'", mailbox_name);
91 char* received = (char*)sg_mailbox_get(mbox);
92 XBT_INFO("I got a '%s'.", received);
93 if (!strcmp(received, "finalize")) { // If it's a finalize message, we're done
100 XBT_INFO("I'm done. See you!");
103 int main(int argc, char* argv[])
105 simgrid_init(&argc, argv);
107 "Usage: %s platform_file deployment_file\n"
108 "\tExample: %s msg_platform.xml msg_deployment.xml\n",
111 simgrid_load_platform(argv[1]);
113 simgrid_register_function("sender", sender);
114 simgrid_register_function("receiver", receiver);
115 simgrid_load_deployment(argv[2]);
119 XBT_INFO("Simulation time %g", simgrid_get_clock());