Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
MC: Support Mutexes in DPOR
[simgrid.git] / examples / cpp / mc-centralized-mutex / s4u-mc-centralized-mutex.cpp
1 /* Copyright (c) 2010-2022. 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 /***************** Centralized Mutual Exclusion Algorithm *********************/
7 /* This example implements a centralized mutual exclusion algorithm.          */
8 /* There is no bug on it, it is just provided to test the state space         */
9 /* reduction of DPOR.                                                         */
10 /******************************************************************************/
11
12 #include "simgrid/s4u.hpp"
13
14 constexpr int AMOUNT_OF_CLIENTS = 4;
15 constexpr int CS_PER_PROCESS    = 2;
16
17 XBT_LOG_NEW_DEFAULT_CATEGORY(centralized, "my log messages");
18
19 class Message {
20 public:
21   enum class Kind { GRANT, REQUEST, RELEASE };
22   Kind kind                             = Kind::GRANT;
23   simgrid::s4u::Mailbox* return_mailbox = nullptr;
24   explicit Message(Message::Kind kind, simgrid::s4u::Mailbox* mbox) : kind(kind), return_mailbox(mbox) {}
25 };
26
27 static void coordinator()
28 {
29   std::queue<simgrid::s4u::Mailbox*> requests;
30   simgrid::s4u::Mailbox* mbox = simgrid::s4u::Mailbox::by_name("coordinator");
31
32   bool CS_used = false;                              // initially the CS is idle
33   int todo     = AMOUNT_OF_CLIENTS * CS_PER_PROCESS; // amount of releases we are expecting
34
35   while (todo > 0) {
36     auto m = mbox->get_unique<Message>();
37     if (m->kind == Message::Kind::REQUEST) {
38       if (CS_used) { // need to push the request in the vector
39         XBT_INFO("CS already used. Queue the request");
40         requests.push(m->return_mailbox);
41       } else { // can serve it immediately
42         XBT_INFO("CS idle. Grant immediately");
43         m->return_mailbox->put(new Message(Message::Kind::GRANT, mbox), 1000);
44         CS_used = true;
45       }
46     } else { // that's a release. Check if someone was waiting for the lock
47       if (not requests.empty()) {
48         XBT_INFO("CS release. Grant to queued requests (queue size: %zu)", requests.size());
49         simgrid::s4u::Mailbox* req = requests.front();
50         requests.pop();
51         req->put(new Message(Message::Kind::GRANT, mbox), 1000);
52         todo--;
53       } else { // nobody wants it
54         XBT_INFO("CS release. resource now idle");
55         CS_used = false;
56         todo--;
57       }
58     }
59   }
60   XBT_INFO("Received all releases, quit now");
61 }
62
63 static void client()
64 {
65   aid_t my_pid = simgrid::s4u::this_actor::get_pid();
66
67   simgrid::s4u::Mailbox* my_mailbox = simgrid::s4u::Mailbox::by_name(std::to_string(my_pid));
68
69   // request the CS 3 times, sleeping a bit in between
70   for (int i = 0; i < CS_PER_PROCESS; i++) {
71     XBT_INFO("Ask the request");
72     simgrid::s4u::Mailbox::by_name("coordinator")->put(new Message(Message::Kind::REQUEST, my_mailbox), 1000);
73     // wait for the answer
74     auto grant = my_mailbox->get_unique<Message>();
75     XBT_INFO("got the answer. Sleep a bit and release it");
76     simgrid::s4u::this_actor::sleep_for(1);
77
78     simgrid::s4u::Mailbox::by_name("coordinator")->put(new Message(Message::Kind::RELEASE, my_mailbox), 1000);
79     simgrid::s4u::this_actor::sleep_for(static_cast<double>(my_pid));
80   }
81   XBT_INFO("Got all the CS I wanted, quit now");
82 }
83
84 int main(int argc, char* argv[])
85 {
86   simgrid::s4u::Engine e(&argc, argv);
87
88   e.load_platform(argv[1]);
89
90   simgrid::s4u::Actor::create("coordinator", e.host_by_name("Tremblay"), coordinator);
91   simgrid::s4u::Actor::create("client", e.host_by_name("Fafard"), client);
92   simgrid::s4u::Actor::create("client", e.host_by_name("Boivin"), client);
93   simgrid::s4u::Actor::create("client", e.host_by_name("Jacquelin"), client);
94   simgrid::s4u::Actor::create("client", e.host_by_name("Ginette"), client);
95
96   e.run();
97
98   return 0;
99 }