Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
7c3841ed023b4cce40749ba859ab536ab9a0b39c
[simgrid.git] / src / s4u / s4u_Mailbox.cpp
1 /* Copyright (c) 2006-2018. 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 "simgrid/s4u/Comm.hpp"
7 #include "simgrid/s4u/Mailbox.hpp"
8 #include "src/msg/msg_private.hpp"
9 #include "src/simix/ActorImpl.hpp"
10 #include "src/simix/smx_network_private.hpp"
11 #include "xbt/log.h"
12
13 XBT_LOG_EXTERNAL_CATEGORY(s4u);
14 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(s4u_channel, s4u, "S4U Communication Mailboxes");
15
16 namespace simgrid {
17 namespace s4u {
18
19 const simgrid::xbt::string& Mailbox::get_name() const
20 {
21   return pimpl_->get_name();
22 }
23
24 const char* Mailbox::get_cname() const
25 {
26   return pimpl_->get_cname();
27 }
28
29 MailboxPtr Mailbox::by_name(const char* name)
30 {
31   kernel::activity::MailboxImpl* mbox = kernel::activity::MailboxImpl::byNameOrNull(name);
32   if (mbox == nullptr) {
33     mbox = simix::simcall([name] { return kernel::activity::MailboxImpl::byNameOrCreate(name); });
34   }
35   return MailboxPtr(&mbox->piface_, true);
36 }
37
38 MailboxPtr Mailbox::by_name(std::string name)
39 {
40   return by_name(name.c_str());
41 }
42
43 bool Mailbox::empty()
44 {
45   return pimpl_->comm_queue.empty();
46 }
47
48 bool Mailbox::listen()
49 {
50   return not this->empty() || (pimpl_->permanent_receiver && not pimpl_->done_comm_queue.empty());
51 }
52
53 smx_activity_t Mailbox::front()
54 {
55   return pimpl_->comm_queue.empty() ? nullptr : pimpl_->comm_queue.front();
56 }
57
58 void Mailbox::set_receiver(ActorPtr actor)
59 {
60   simix::simcall([this, actor]() { this->pimpl_->setReceiver(actor); });
61 }
62
63 /** @brief get the receiver (process associated to the mailbox) */
64 ActorPtr Mailbox::get_receiver()
65 {
66   if (pimpl_->permanent_receiver == nullptr)
67     return ActorPtr();
68   return pimpl_->permanent_receiver->iface();
69 }
70
71 CommPtr Mailbox::put_init()
72 {
73   CommPtr res   = CommPtr(new s4u::Comm());
74   res->sender_  = SIMIX_process_self();
75   res->mailbox_ = this;
76   return res;
77 }
78 s4u::CommPtr Mailbox::put_init(void* data, uint64_t simulated_size_in_bytes)
79 {
80   s4u::CommPtr res = put_init();
81   res->set_remaining(simulated_size_in_bytes);
82   res->src_buff_      = data;
83   res->src_buff_size_ = sizeof(void*);
84   return res;
85 }
86 s4u::CommPtr Mailbox::put_async(void* payload, uint64_t simulated_size_in_bytes)
87 {
88   xbt_assert(payload != nullptr, "You cannot send nullptr");
89
90   s4u::CommPtr res = put_init(payload, simulated_size_in_bytes);
91   res->start();
92   return res;
93 }
94 void Mailbox::put(void* payload, uint64_t simulated_size_in_bytes)
95 {
96   xbt_assert(payload != nullptr, "You cannot send nullptr");
97
98   CommPtr c = put_init();
99   c->set_remaining(simulated_size_in_bytes);
100   c->set_src_data(payload);
101   c->wait();
102 }
103 /** Blocking send with timeout */
104 void Mailbox::put(void* payload, uint64_t simulated_size_in_bytes, double timeout)
105 {
106   xbt_assert(payload != nullptr, "You cannot send nullptr");
107
108   CommPtr c = put_init();
109   c->set_remaining(simulated_size_in_bytes);
110   c->set_src_data(payload);
111   // c->start() is optional.
112   c->wait(timeout);
113 }
114
115 s4u::CommPtr Mailbox::get_init()
116 {
117   CommPtr res    = CommPtr(new s4u::Comm());
118   res->receiver_ = SIMIX_process_self();
119   res->mailbox_  = this;
120   return res;
121 }
122 s4u::CommPtr Mailbox::get_async(void** data)
123 {
124   s4u::CommPtr res = get_init();
125   res->set_dst_data(data, sizeof(*data));
126   res->start();
127   return res;
128 }
129
130 void* Mailbox::get()
131 {
132   void* res = nullptr;
133   CommPtr c = get_init();
134   c->set_dst_data(&res, sizeof(res));
135   c->wait();
136   return res;
137 }
138 void* Mailbox::get(double timeout)
139 {
140   void* res = nullptr;
141   CommPtr c = get_init();
142   c->set_dst_data(&res, sizeof(res));
143   c->wait(timeout);
144   return res;
145 }
146 } // namespace s4u
147 } // namespace simgrid
148
149 /* **************************** Public C interface *************************** */
150 /** \brief Set the mailbox to receive in asynchronous mode
151  *
152  * All messages sent to this mailbox will be transferred to the receiver without waiting for the receive call.
153  * The receive call will still be necessary to use the received data.
154  * If there is a need to receive some messages asynchronously, and some not, two different mailboxes should be used.
155  *
156  * \param alias The name of the mailbox
157  */
158 void sg_mailbox_set_receiver(const char* alias)
159 {
160   simgrid::s4u::Mailbox::by_name(alias)->set_receiver(simgrid::s4u::Actor::self());
161   XBT_VERB("%s mailbox set to receive eagerly for myself\n", alias);
162 }
163
164 /** \brief Check if there is a communication going on in a mailbox.
165  *
166  * \param alias the name of the mailbox to be considered
167  * \return Returns 1 if there is a communication, 0 otherwise
168  */
169 int sg_mailbox_listen(const char* alias)
170 {
171   return simgrid::s4u::Mailbox::by_name(alias)->listen() ? 1 : 0;
172 }