Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
ad182f233a27805a0afbeb7499267dc9b51fa5e8
[simgrid.git] / src / kernel / activity / MailboxImpl.cpp
1 /* Copyright (c) 2007-2019. 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 #include "src/kernel/activity/MailboxImpl.hpp"
7 #include "src/kernel/activity/CommImpl.hpp"
8
9 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(simix_mailbox, simix, "Mailbox implementation");
10
11 static std::map<std::string, smx_mailbox_t>* mailboxes = new std::map<std::string, smx_mailbox_t>;
12
13 void SIMIX_mailbox_exit()
14 {
15   for (auto const& elm : *mailboxes)
16     delete elm.second;
17   delete mailboxes;
18 }
19
20 /******************************************************************************/
21 /*                           Rendez-Vous Points                               */
22 /******************************************************************************/
23
24 namespace simgrid {
25 namespace kernel {
26 namespace activity {
27 /** @brief Returns the mailbox of that name, or nullptr */
28 MailboxImpl* MailboxImpl::by_name_or_null(const std::string& name)
29 {
30   auto mbox = mailboxes->find(name);
31   if (mbox != mailboxes->end())
32     return mbox->second;
33   else
34     return nullptr;
35 }
36
37 /** @brief Returns the mailbox of that name, newly created on need */
38 MailboxImpl* MailboxImpl::by_name_or_create(const std::string& name)
39 {
40   /* two processes may have pushed the same mbox_create simcall at the same time */
41   auto m = mailboxes->find(name);
42   if (m == mailboxes->end()) {
43     smx_mailbox_t mbox = new MailboxImpl(name);
44     XBT_DEBUG("Creating a mailbox at %p with name %s", mbox, name.c_str());
45     (*mailboxes)[mbox->name_] = mbox;
46     return mbox;
47   } else
48     return m->second;
49 }
50 /** @brief set the receiver of the mailbox to allow eager sends
51  *  @param actor The receiving dude
52  */
53 void MailboxImpl::set_receiver(s4u::ActorPtr actor)
54 {
55   if (actor != nullptr)
56     this->permanent_receiver_ = actor->get_impl();
57   else
58     this->permanent_receiver_ = nullptr;
59 }
60 /** @brief Pushes a communication activity into a mailbox
61  *  @param comm What to add
62  */
63 void MailboxImpl::push(CommImplPtr comm)
64 {
65   comm->mbox = this;
66   this->comm_queue_.push_back(std::move(comm));
67 }
68
69 /** @brief Removes a communication activity from a mailbox
70  *  @param comm What to remove
71  */
72 void MailboxImpl::remove(const CommImplPtr& comm)
73 {
74   xbt_assert(comm->mbox == this, "Comm %p is in mailbox %s, not mailbox %s", comm.get(),
75              (comm->mbox ? comm->mbox->get_cname() : "(null)"), this->get_cname());
76   comm->mbox = nullptr;
77   for (auto it = this->comm_queue_.begin(); it != this->comm_queue_.end(); it++)
78     if (*it == comm) {
79       this->comm_queue_.erase(it);
80       return;
81     }
82   xbt_die("Comm %p not found in mailbox %s", comm.get(), this->get_cname());
83 }
84
85 CommImplPtr MailboxImpl::iprobe(int type, int (*match_fun)(void*, void*, CommImpl*), void* data)
86 {
87   XBT_DEBUG("iprobe from %p %p", this, &comm_queue_);
88
89   CommImplPtr this_comm;
90   CommImpl::Type smx_type;
91   if (type == 1) {
92     this_comm = CommImplPtr(new CommImpl(CommImpl::Type::SEND));
93     smx_type  = CommImpl::Type::RECEIVE;
94   } else {
95     this_comm = CommImplPtr(new CommImpl(CommImpl::Type::RECEIVE));
96     smx_type  = CommImpl::Type::SEND;
97   }
98   CommImplPtr other_comm = nullptr;
99   if (permanent_receiver_ != nullptr && not done_comm_queue_.empty()) {
100     XBT_DEBUG("first check in the permanent recv mailbox, to see if we already got something");
101     other_comm = find_matching_comm(smx_type, match_fun, data, this_comm, /*done*/ true, /*remove_matching*/ false);
102   }
103   if (not other_comm) {
104     XBT_DEBUG("check if we have more luck in the normal mailbox");
105     other_comm = find_matching_comm(smx_type, match_fun, data, this_comm, /*done*/ false, /*remove_matching*/ false);
106   }
107
108   return other_comm;
109 }
110
111 /**
112  *  @brief Checks if there is a communication activity queued in comm_queue_ matching our needs
113  *  @param type The type of communication we are looking for (comm_send, comm_recv)
114  *  @param match_fun the function to apply
115  *  @param this_user_data additional parameter to the match_fun
116  *  @param my_synchro what to compare against
117  *  @param remove_matching whether or not to clean the found object from the queue
118  *  @return The communication activity if found, nullptr otherwise
119  */
120 CommImplPtr MailboxImpl::find_matching_comm(CommImpl::Type type, int (*match_fun)(void*, void*, CommImpl*),
121                                             void* this_user_data, const CommImplPtr& my_synchro, bool done,
122                                             bool remove_matching)
123 {
124   void* other_user_data = nullptr;
125   auto& comm_queue      = done ? done_comm_queue_ : comm_queue_;
126
127   for (auto it = comm_queue.begin(); it != comm_queue.end(); it++) {
128     CommImplPtr& comm = *it;
129
130     if (comm->type == CommImpl::Type::SEND) {
131       other_user_data = comm->src_data_;
132     } else if (comm->type == CommImpl::Type::RECEIVE) {
133       other_user_data = comm->dst_data_;
134     }
135     if (comm->type == type && (match_fun == nullptr || match_fun(this_user_data, other_user_data, comm.get())) &&
136         (not comm->match_fun || comm->match_fun(other_user_data, this_user_data, my_synchro.get()))) {
137       XBT_DEBUG("Found a matching communication synchro %p", comm.get());
138 #if SIMGRID_HAVE_MC
139       comm->mbox_cpy = comm->mbox;
140 #endif
141       comm->mbox = nullptr;
142       CommImplPtr comm_cpy = comm;
143       if (remove_matching)
144         comm_queue.erase(it);
145       return comm_cpy;
146     }
147     XBT_DEBUG("Sorry, communication synchro %p does not match our needs:"
148               " its type is %d but we are looking for a comm of type %d (or maybe the filtering didn't match)",
149               comm.get(), (int)comm->type, (int)type);
150   }
151   XBT_DEBUG("No matching communication synchro found");
152   return nullptr;
153 }
154 }
155 }
156 }