Arcane  4.2.3.0
Developer documentation
Loading...
Searching...
No Matches
SharedMemoryMessageQueue.cc
1// -*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
2//-----------------------------------------------------------------------------
3// Copyright 2000-2026 CEA (www.cea.fr) IFPEN (www.ifpenergiesnouvelles.com)
4// See the top-level COPYRIGHT file for details.
5// SPDX-License-Identifier: Apache-2.0
6//-----------------------------------------------------------------------------
7/*---------------------------------------------------------------------------*/
8/* SharedMemoryMessageQueue.cc (C) 2000-2026 */
9/* */
10/* Implementation of a shared memory message queue. */
11/*---------------------------------------------------------------------------*/
12/*---------------------------------------------------------------------------*/
13
14#include "arcane/utils/FatalErrorException.h"
15#include "arcane/utils/NotImplementedException.h"
16#include "arcane/utils/NotSupportedException.h"
17#include "arcane/utils/ArgumentException.h"
18#include "arcane/utils/ITraceMng.h"
19#include "arcane/utils/ValueConvert.h"
20#include "arcane/utils/SmallArray.h"
21
22#include "arccore/common/internal/MemoryResourceMng.h"
23
24#include "arcane/parallel/thread/SharedMemoryMessageQueue.h"
25#include "arcane/parallel/thread/IAsyncQueue.h"
26
27#include "arcane/core/ISerializeMessage.h"
28
29// Macro to display messages for debugging
30#define TRACE_DEBUG(format_str, ...) \
31 if (m_is_debug && m_trace_mng) { \
32 m_trace_mng->info() << String::format(format_str, __VA_ARGS__); \
33 m_trace_mng->flush(); \
34 }
35
36/*---------------------------------------------------------------------------*/
37/*---------------------------------------------------------------------------*/
38
40{
41
42/*---------------------------------------------------------------------------*/
43/*---------------------------------------------------------------------------*/
55{
56 SendBufferInfo send_info = sender->sendBufferInfo();
57 ReceiveBufferInfo receive_info = this->receiveBufferInfo();
58
59 const ISerializer* send_serializer = send_info.serializer();
60 ISerializer* receive_serializer = receive_info.serializer();
61 if (receive_serializer) {
62 if (!send_serializer)
63 ARCANE_FATAL("No send serializer for receive serializer");
64 receive_serializer->copy(send_serializer);
65 return;
66 }
67
68 ByteConstSpan send_span = send_info.memoryBuffer();
69 ByteSpan receive_span = receive_info.memoryBuffer();
70 Int64 send_size = send_span.size();
71 Int64 receive_size = receive_span.size();
72 if (send_size > receive_size)
73 ARCANE_FATAL("Not enough memory for receiving message receive={0} send={1}",
74 receive_size, send_size);
75
77}
78
79/*---------------------------------------------------------------------------*/
80/*---------------------------------------------------------------------------*/
81
82void SharedMemoryMessageRequest::
83destroy()
84{
85 if (m_is_destroyed)
86 ARCANE_FATAL("Request already destroyed");
87 m_is_destroyed = true;
88 // Comment out for debug.
89 delete this;
90}
91
92/*---------------------------------------------------------------------------*/
93/*---------------------------------------------------------------------------*/
94
95std::ostream&
96operator<<(std::ostream& o, const SharedMemoryMessageRequest& v)
97{
98 o << "(id=" << v.id() << " queue=" << v.queueName()
99 << " orig=" << v.orig() << " dest=" << v.dest()
100 << " tag=" << v.tag() << " is_recv?=" << v.isRecv()
101 << " is_done=?" << v.isDone()
102 << " send_size=" << v.m_send_buffer_info.memoryBuffer().size()
103 << " receive_size=" << v.m_receive_buffer_info.memoryBuffer().size()
104 << ")";
105 return o;
106}
107
108/*---------------------------------------------------------------------------*/
109/*---------------------------------------------------------------------------*/
115class RequestAsyncQueue
116{
117 public:
118
119 RequestAsyncQueue()
120 : m_async_queue(IAsyncQueue::createQueue())
121 {}
122 ~RequestAsyncQueue()
123 {
124 delete m_async_queue;
125 }
126
127 public:
128
129 void push(SharedMemoryMessageRequest* v)
130 {
131 m_async_queue->push(v);
132 }
134 {
135 return static_cast<SharedMemoryMessageRequest*>(m_async_queue->pop());
136 }
138 {
139 return static_cast<SharedMemoryMessageRequest*>(m_async_queue->tryPop());
140 }
141
142 private:
143
144 IAsyncQueue* m_async_queue = nullptr;
145};
146
147/*---------------------------------------------------------------------------*/
148/*---------------------------------------------------------------------------*/
149
150/*---------------------------------------------------------------------------*/
151/*---------------------------------------------------------------------------*/
163{
164 static MessageTag SERIALIZER_TAG() { return MessageTag(125); }
165
166 public:
167
168 SubQueue(SharedMemoryMessageQueue* master_queue, MessageRank rank);
169
170 public:
171
172 MessageRank rank() const { return m_rank; }
173 void setTraceMng(ITraceMng* tm) { m_trace_mng = tm; }
174 ITraceMng* traceMng() const { return m_trace_mng; }
175 void wait(SharedMemoryMessageRequest* tmr);
176 void testRequest(SharedMemoryMessageRequest* tmr);
177 void waitRequestAvailable();
178 void checkRequestAvailable();
179 void waitSome(ArrayView<Request> requests, ArrayView<bool> requests_done, bool is_non_blocking);
180 MessageId probe(const PointToPointMessageInfo& message);
181 MessageSourceInfo legacyProbe(const PointToPointMessageInfo& message);
182 void setName(const String& name) { m_name = name; }
183 const String& name() const { return m_name; }
184
185 public:
186
188 addReceive(Int64 request_id, const PointToPointMessageInfo& message, ReceiveBufferInfo buf);
190 addSend(Int64 request_id, const PointToPointMessageInfo& message, SendBufferInfo buf);
191
192 private:
193
194 SharedMemoryMessageQueue* m_master_queue = nullptr;
195 MessageRank m_rank;
199 RequestAsyncQueue m_async_message_queue;
200 ITraceMng* m_trace_mng = nullptr;
201 bool m_is_debug = false;
202 bool m_is_allow_null_rank_for_any_source = true;
203 String m_name;
204
205 private:
206
207 void _removeRequest(SharedMemoryMessageRequest* tmr, Array<SharedMemoryMessageRequest*>& requests);
208 bool _checkSendDone(SharedMemoryMessageRequest* tmr_send);
209 bool _checkRecvDone(SharedMemoryMessageRequest* tmr_recv);
210 void _checkRequestDone(SharedMemoryMessageRequest* tmr);
213 _getMatchingSendRequest(MessageRank recv_dest, MessageRank recv_orig, MessageTag tag);
214 void _testOrWaitRequestAvailable(bool is_blocking);
216 _createReceiveRequest(Int64 request_id, MessageRank dest, MessageTag tag,
217 ReceiveBufferInfo receive_buffer);
219 _createSendRequest(Int64 request_id, MessageRank orig, MessageTag tag,
220 SendBufferInfo send_buffer);
221};
222
223/*---------------------------------------------------------------------------*/
224/*---------------------------------------------------------------------------*/
225
226SharedMemoryMessageQueue::SubQueue::
227SubQueue(SharedMemoryMessageQueue* master_queue, MessageRank rank)
228: m_master_queue(master_queue)
229, m_rank(rank)
230{
231 if (auto v = Convert::Type<Int32>::tryParseFromEnvironment("ARCCORE_ALLOW_NULL_RANK_FOR_MPI_ANY_SOURCE", true))
232 m_is_allow_null_rank_for_any_source = v.value() != 0;
233 m_name = String::format("queue{0}", rank);
234 if (auto v = Convert::Type<Int32>::tryParseFromEnvironment("ARCANE_DEBUG_SHAREDMEMORY_MESSAGEPASSING", true))
235 m_is_debug = (v.value() != 0);
236}
237
238/*---------------------------------------------------------------------------*/
239/*---------------------------------------------------------------------------*/
240
241/*---------------------------------------------------------------------------*/
242/*---------------------------------------------------------------------------*/
243
244SharedMemoryMessageRequest* SharedMemoryMessageQueue::SubQueue::
245_createReceiveRequest(Int64 request_id, MessageRank dest,
246 MessageTag tag, ReceiveBufferInfo receive_buffer)
247{
248 auto* tmr = new SharedMemoryMessageRequest(this, request_id, m_rank, dest, tag, receive_buffer);
249 return tmr;
250}
251
252/*---------------------------------------------------------------------------*/
253/*---------------------------------------------------------------------------*/
254
255SharedMemoryMessageRequest* SharedMemoryMessageQueue::SubQueue::
256_createSendRequest(Int64 request_id, MessageRank orig,
257 MessageTag tag, SendBufferInfo send_buffer)
258{
259 SubQueue* queue = m_master_queue->_getSubQueue(orig);
260 auto* tmr = new SharedMemoryMessageRequest(queue, request_id, orig, m_rank, tag, send_buffer);
261 return tmr;
262}
263
264/*---------------------------------------------------------------------------*/
265/*---------------------------------------------------------------------------*/
266
267SharedMemoryMessageRequest* SharedMemoryMessageQueue::SubQueue::
268addReceive(Int64 request_id, const PointToPointMessageInfo& message, ReceiveBufferInfo buf)
269{
270 SharedMemoryMessageRequest* tmr = nullptr;
271 if (message.isRankTag()) {
272 MessageTag tag = message.tag();
273 MessageRank dest = message.destinationRank();
274 tmr = _createReceiveRequest(request_id, dest, tag, buf);
275 TRACE_DEBUG("** ADD RECV queue={0} id={1} ORIG={2} DEST={3} tmr={4} size={5} serializer={6}",
276 m_name, request_id, m_rank, dest, tag, *tmr, buf.memoryBuffer().size(), buf.serializer());
277 }
278 else if (message.isMessageId()) {
279 MessageId message_id = message.messageId();
280 MessageId::SourceInfo si = message_id.sourceInfo();
281 MessageRank dest = si.rank();
282 MessageTag tag = si.tag();
283
284 // We know the 'send' request that matches this one. We must therefore
285 // position it in \a tmr now to ensure that the correct one is used.
286 // To do this, search for the send corresponding to the ID of our request
287 Int64 req_id = (size_t)message_id;
288 SharedMemoryMessageRequest* send_request = nullptr;
289 for (Integer i = 0, n = m_send_requests.size(); i < n; ++i)
290 if (m_send_requests[i]->id() == req_id) {
291 send_request = m_send_requests[i];
292 break;
293 }
294 if (!send_request)
295 ARCANE_FATAL("Can not find matching send request from MessageId");
296
297 tmr = _createReceiveRequest(request_id, dest, tag, buf);
298 TRACE_DEBUG("** ADD RECV FromMessageId queue={0} req_id={1} ORIG={2} DEST={3} tmr={4} size={5} serializer={6}",
299 m_name, request_id, m_rank, dest, *tmr, buf.memoryBuffer().size(), buf.serializer());
300 tmr->setMatchingSendRequest(send_request);
301 }
302 else
303 ARCANE_THROW(NotSupportedException, "Invalid 'MessageInfo'");
304
305 m_recv_requests.add(tmr);
306 return tmr;
307}
308
309/*---------------------------------------------------------------------------*/
310/*---------------------------------------------------------------------------*/
311
312SharedMemoryMessageRequest* SharedMemoryMessageQueue::SubQueue::
313addSend(Int64 request_id, const PointToPointMessageInfo& message, SendBufferInfo buf)
314{
315 MessageTag tag = message.tag();
316 if (tag.isNull())
317 ARCANE_THROW(ArgumentException, "null tag");
318 MessageRank orig = message.emiterRank();
319 auto* tmr = _createSendRequest(request_id, orig, tag, buf);
320 m_async_message_queue.push(tmr);
321 TRACE_DEBUG("** ADD SEND queue={0} ORIG={1} DEST={2} tag={3} size={4} tmr={5} serializer={6}",
322 m_name, orig, m_rank, tag, buf.memoryBuffer().size(), *tmr, buf.serializer());
323 return tmr;
324}
325
326/*---------------------------------------------------------------------------*/
327/*---------------------------------------------------------------------------*/
328
329void SharedMemoryMessageQueue::SubQueue::
330_checkRequestDone(SharedMemoryMessageRequest* tmr)
331{
332 if (tmr->isDone())
333 ARCANE_FATAL("Can not check already done request");
334
335 if (tmr->isRecv())
336 _checkRecvDone(tmr);
337 else
338 _checkSendDone(tmr);
339}
340
341/*---------------------------------------------------------------------------*/
342/*---------------------------------------------------------------------------*/
343
351{
352 if (tmr->isDone()) {
353 if (tmr->isRecv())
354 _removeRequest(tmr, m_recv_requests);
355 else
356 _removeRequest(tmr, m_done_requests);
357 }
358}
359
360/*---------------------------------------------------------------------------*/
361/*---------------------------------------------------------------------------*/
362
363void SharedMemoryMessageQueue::SubQueue::
364_testOrWaitRequestAvailable(bool is_blocking)
365{
366 SharedMemoryMessageRequest* sq = nullptr;
367 if (is_blocking) {
368 sq = m_async_message_queue.pop();
369 }
370 else
371 sq = m_async_message_queue.tryPop();
372 if (sq) {
373 if (sq->orig() == m_rank) {
374 m_done_requests.add(sq);
375 }
376 else {
377 m_send_requests.add(sq);
378 }
379 }
380}
381
382/*---------------------------------------------------------------------------*/
383/*---------------------------------------------------------------------------*/
384
385void SharedMemoryMessageQueue::SubQueue::
386waitRequestAvailable()
387{
388 // Blocks until a message is received.
389 _testOrWaitRequestAvailable(true);
390}
391
392/*---------------------------------------------------------------------------*/
393/*---------------------------------------------------------------------------*/
394
395void SharedMemoryMessageQueue::SubQueue::
396checkRequestAvailable()
397{
398 _testOrWaitRequestAvailable(false);
399}
400
401/*---------------------------------------------------------------------------*/
402/*---------------------------------------------------------------------------*/
403
404void SharedMemoryMessageQueue::SubQueue::
405wait(SharedMemoryMessageRequest* tmr)
406{
407 if (tmr->queue() != this)
408 ARCANE_FATAL("Bad queue");
409 TRACE_DEBUG("**** WAIT FOR_MESSAGE queue={0} tmr={1} nb_send={2} nb_done={3}",
410 m_name, *tmr, m_rank, m_send_requests.size(), m_done_requests.size());
411
412 while (!tmr->isDone()) {
413 _checkRequestDone(tmr);
414
415 if (!tmr->isDone()) {
416 // Blocks until a message is received.
417 waitRequestAvailable();
418 }
419 }
420
421 _cleanupRequestIfDone(tmr);
422}
423
424/*---------------------------------------------------------------------------*/
425/*---------------------------------------------------------------------------*/
426
427void SharedMemoryMessageQueue::SubQueue::
428testRequest(SharedMemoryMessageRequest* tmr)
429{
430 if (tmr->queue() != this)
431 ARCANE_FATAL("Bad queue");
432
433 _checkRequestDone(tmr);
434 _cleanupRequestIfDone(tmr);
435}
436
437/*---------------------------------------------------------------------------*/
438/*---------------------------------------------------------------------------*/
439
440void SharedMemoryMessageQueue::SubQueue::
441_removeRequest(SharedMemoryMessageRequest* tmr, Array<SharedMemoryMessageRequest*>& requests)
442{
443 // TODO traiter les requêtes invalides (tmr==nullptr);
444 for (Integer i = 0, n = requests.size(); i < n; ++i) {
445 SharedMemoryMessageRequest* tmr2 = requests[i];
446 if (tmr == tmr2) {
447 requests.remove(i);
448 return;
449 }
450 }
451 ARCANE_FATAL("Can not remove request");
452}
453
454/*---------------------------------------------------------------------------*/
455/*---------------------------------------------------------------------------*/
456
457bool SharedMemoryMessageQueue::SubQueue::
458_checkSendDone(SharedMemoryMessageRequest* tmr_send)
459{
460 for (SharedMemoryMessageRequest* tmr : m_done_requests) {
461 if (tmr == tmr_send) {
462 tmr_send->setDone(true);
463 return true;
464 }
465 }
466 return false;
467}
468
469/*---------------------------------------------------------------------------*/
470/*---------------------------------------------------------------------------*/
471/*
472 * \brief Checks if a send message matches the request \a tmr_recv.
473 *
474 * Checks if a request in the list of sent messages matches
475 * \a tmr_recv. This is the case if the source/destination pair is suitable
476 * or if the destination is A_NULL_RANK (which corresponds to MPI_ANY_SOURCE
477 * in the MPI case).
478 * It is important to process requests in order of arrival to comply with the MPI standard.
479 *
480 * \retval true if a matching request was found.
481 * \retval false otherwise.
482 */
483SharedMemoryMessageRequest* SharedMemoryMessageQueue::SubQueue::
484_getMatchingSendRequest(MessageRank recv_dest, MessageRank recv_orig, MessageTag tag)
485{
486 bool is_any_tag = tag.isNull();
487 bool is_any_dest = recv_dest.isNull() || recv_dest.isAnySource();
488 if (recv_dest.isNull() && !m_is_allow_null_rank_for_any_source)
489 ARCANE_FATAL("Can not use probe() with null rank. Use MessageRank::anySourceRank() instead");
490 for (Integer j = 0, n = m_send_requests.size(); j < n; ++j) {
491 SharedMemoryMessageRequest* tmr_send = m_send_requests[j];
492 TRACE_DEBUG("CHECK RECV DONE queue={0} tmr_send={1} recv_dest={2}"
493 " recv_orig={3} request={4}/{5}",
494 m_name, *tmr_send, recv_dest, recv_orig,
495 j, n);
496 if (recv_orig == tmr_send->dest()) {
497 bool is_rank_ok = (recv_dest == tmr_send->orig()) || (is_any_dest && m_rank == recv_orig);
498 bool is_tag_ok = (is_any_tag || tmr_send->tag() == tag);
499 if (is_rank_ok && is_tag_ok) {
500 TRACE_DEBUG("CHECK RECV DONE found: queue={0} tmr_send={1}", m_name, *tmr_send);
501 return tmr_send;
502 }
503 }
504 }
505 return nullptr;
506}
507
508/*---------------------------------------------------------------------------*/
509/*---------------------------------------------------------------------------*/
510
511bool SharedMemoryMessageQueue::SubQueue::
512_checkRecvDone(SharedMemoryMessageRequest* tmr_recv)
513{
514 // Checks if the send is already associated with our request. This is the case
515 // if we used a probe() call.
516 auto* tmr_send = tmr_recv->matchingSendRequest();
517 if (!tmr_send)
518 tmr_send = _getMatchingSendRequest(tmr_recv->dest(), tmr_recv->orig(), tmr_recv->tag());
519 if (tmr_send) {
520 tmr_recv->setSource(tmr_send->orig());
521 tmr_recv->copyFromSender(tmr_send);
522 tmr_recv->setDone(true);
523 tmr_send->queue()->m_async_message_queue.push(tmr_send);
524 _removeRequest(tmr_send, m_send_requests);
525 return true;
526 }
527 return false;
528}
529
530/*---------------------------------------------------------------------------*/
531/*---------------------------------------------------------------------------*/
532
533void SharedMemoryMessageQueue::SubQueue::
534waitSome(ArrayView<Request> requests, ArrayView<bool> requests_done,
535 bool is_non_blocking)
536{
537 Integer nb_request = requests.size();
538 requests_done.fill(false);
539 bool one_request_done = false;
540 TRACE_DEBUG("** WAIT SOME REQUEST queue={0} rank={1} nb_request={2}\n", m_name, m_rank, nb_request);
541 while (!one_request_done) {
542 if (is_non_blocking)
543 checkRequestAvailable();
544 bool has_valid_request = false;
545 for (Integer i = 0; i < nb_request; ++i) {
546 Request request = requests[i];
547 if (!request.isValid())
548 continue;
549 SharedMemoryMessageRequest* tmr = requests[i];
550 if (!tmr)
551 continue;
552 this->testRequest(tmr);
553 if (tmr->isDone()) {
554 one_request_done = true;
555 requests_done[i] = true;
556 tmr->destroy();
557 if (requests[i].hasSubRequest())
558 ARCANE_THROW(NotImplementedException, "handling of sub requests");
559 requests[i].reset();
560 }
561 has_valid_request = true;
562 }
563 // If at least one request is completed, exit the loop.
564 if (one_request_done)
565 break;
566 // If not, no request succeeded. We block until there is
567 // a message in the queue unless there are no valid requests
568 // (This is possible if all requests in the list are null requests).
569 if (!has_valid_request)
570 break;
571 // In non-blocking mode, we already tested at the beginning of the loop if
572 // a request is available. If we are here, we can exit directly
573 // otherwise we will block.
574 if (is_non_blocking)
575 break;
576 TRACE_DEBUG("** WAIT REQUEST AVAILABLE rank={0}", m_rank);
577 waitRequestAvailable();
578 }
579}
580
581/*---------------------------------------------------------------------------*/
582/*---------------------------------------------------------------------------*/
583
584MP::MessageId SharedMemoryMessageQueue::SubQueue::
585probe(const MP::PointToPointMessageInfo& message)
586{
587 TRACE_DEBUG("Probe rank={0} nb_send={1} nb_receive={2} queue={3} is_valid={4}",
588 m_rank, m_send_requests.size(), m_recv_requests.size(), this, message.isValid());
589 if (!message.isValid())
590 return MessageId();
591
592 // The message must be initialized with a (rank/tag) pair.
593 if (!message.isRankTag())
594 ARCCORE_FATAL("Invalid message_info: message.isRankTag() is false");
595
596 MessageRank rank = message.destinationRank();
597 MessageTag tag = message.tag();
598 bool is_blocking = message.isBlocking();
599 if (is_blocking)
600 ARCANE_THROW(NotImplementedException, "blocking probe");
601
602 // TODO: look into adding anti-loop safety
603 // TODO: we should check that if this
604 // method is called twice with the same information, the same message is not retrieved.
605 // When that is the case, legacyProbe() will need to be modified accordingly.
606 for (;;) {
607 _testOrWaitRequestAvailable(is_blocking);
608 auto* req = _getMatchingSendRequest(rank, m_rank, tag);
609 if (req) {
610 // TODO: Verify that the request has a buffer and not an 'ISerializer'.
611 Int64 send_size = req->sendBufferInfo().memoryBuffer().size();
612 MessageId::SourceInfo si(req->orig(), req->tag(), send_size);
613 return MessageId(si, (size_t)req->id());
614 }
615 if (!is_blocking)
616 // In non-blocking mode, exit the loop even if no request is found.
617 break;
618 }
619 return {};
620}
621
622/*---------------------------------------------------------------------------*/
623/*---------------------------------------------------------------------------*/
624
625MP::MessageSourceInfo SharedMemoryMessageQueue::SubQueue::
626legacyProbe(const MP::PointToPointMessageInfo& message)
627{
628 // Performs a normal probe but does not retain message information.
629 // NOTE: this works because probe() can return the same
630 // message multiple times. When that is no longer the case, this will need to be modified.
631 MP::MessageId message_id = probe(message);
632 if (message_id.isValid())
633 return message_id.sourceInfo();
634 return {};
635}
636
637/*---------------------------------------------------------------------------*/
638/*---------------------------------------------------------------------------*/
639
640/*---------------------------------------------------------------------------*/
641/*---------------------------------------------------------------------------*/
642
643SharedMemoryMessageQueue::
644~SharedMemoryMessageQueue()
645{
646 for (SubQueue* sq : m_sub_queues)
647 delete sq;
648}
649
650/*---------------------------------------------------------------------------*/
651/*---------------------------------------------------------------------------*/
652
653void SharedMemoryMessageQueue::
654init(Integer nb_thread)
655{
656 m_atomic_request_id = 1;
657 m_nb_thread = nb_thread;
658 Integer nb_queue = nb_thread;
659 m_sub_queues.resize(nb_queue);
660 for (Integer i = 0; i < nb_queue; ++i) {
661 m_sub_queues[i] = new SubQueue(this, MessageRank(i));
662 }
663}
664
665/*---------------------------------------------------------------------------*/
666/*---------------------------------------------------------------------------*/
667
668SharedMemoryMessageQueue::SubQueue* SharedMemoryMessageQueue::
669_getSourceSubQueue(const MP::PointToPointMessageInfo& message)
670{
671 MessageRank orig = message.emiterRank();
672 if (orig.isNull())
673 ARCANE_THROW(ArgumentException, "null message.sourceRank()");
674 return _getSubQueue(orig);
675}
676
677/*---------------------------------------------------------------------------*/
678/*---------------------------------------------------------------------------*/
679
680SharedMemoryMessageQueue::SubQueue* SharedMemoryMessageQueue::
681_getDestinationSubQueue(const MP::PointToPointMessageInfo& message)
682{
683 MessageRank dest = message.destinationRank();
684 if (dest.isNull())
685 ARCANE_THROW(ArgumentException, "null message.destinationRank()");
686 return _getSubQueue(dest);
687}
688
689/*---------------------------------------------------------------------------*/
690/*---------------------------------------------------------------------------*/
691
692void SharedMemoryMessageQueue::
693waitAll(Int32 calling_rank, ArrayView<Request> requests)
694{
695 Integer nb_request = requests.size();
696 // To prevent blocking, the requests must be processed
697 // in ascending order of queues, and 'receive' FIRST!!
698 UniqueArray<SharedMemoryMessageRequest*> sorted_requests(nb_request);
699 for (Integer i = 0; i < nb_request; ++i) {
700 sorted_requests[i] = requests[i];
701 }
702 std::sort(std::begin(sorted_requests), std::end(sorted_requests),
703 SharedMemoryMessageRequest::SortFunctor(m_nb_thread));
704
705#if 0
706 for( Integer i=0; i<nb_request; ++i ){
707 SharedMemoryMessageRequest* tmr = sorted_requests[i];
708 cout << String::format("** WAIT FOR REQUEST tmr={0}\n",tmr);
709 }
710#endif
711 auto own_queue = _getSubQueue(MessageRank(calling_rank));
712 int method = 0;
713 if (method == 0) {
714 for (Integer i = 0; i < nb_request; ++i) {
715 SharedMemoryMessageRequest* tmr = sorted_requests[i];
716 if (tmr) {
717 SubQueue* sub_queue = tmr->queue();
718 if (own_queue != sub_queue)
719 ARCANE_FATAL("Bad queue onw={0} sub={1}", own_queue->name(), sub_queue->name());
720 sub_queue->wait(tmr);
721 tmr->destroy();
722 }
723 }
724 }
725 else if (method == 1) {
726 Int32 nb_done = 0;
727 while (nb_done != nb_request) {
728 for (Integer i = 0; i < nb_request; ++i) {
729 SharedMemoryMessageRequest* tmr = sorted_requests[i];
730 if (!tmr)
731 continue;
732 SubQueue* sub_queue = tmr->queue();
733 if (own_queue != sub_queue)
734 ARCANE_FATAL("Bad queue onw={0} sub={1}", own_queue->name(), sub_queue->name());
735 sub_queue->testRequest(tmr);
736 if (tmr->isDone()) {
737 tmr->destroy();
738 sorted_requests[i] = nullptr;
739 ++nb_done;
740 }
741 if (nb_done == nb_request)
742 break;
743 }
744 if (nb_done != nb_request) {
745 own_queue->waitRequestAvailable();
746 }
747 }
748 }
749 for (Integer i = 0; i < nb_request; ++i) {
750 if (requests[i].hasSubRequest())
751 ARCANE_THROW(NotImplementedException, "handling of sub requests");
752 requests[i].reset();
753 }
754}
755
756/*---------------------------------------------------------------------------*/
757/*---------------------------------------------------------------------------*/
758
759void SharedMemoryMessageQueue::
760waitSome(Int32 rank, ArrayView<Parallel::Request> requests,
761 ArrayView<bool> requests_done, bool is_non_blocking)
762{
763 requests_done.fill(false);
764 auto sub_queue = _getSubQueue(MessageRank(rank));
765 sub_queue->waitSome(requests, requests_done, is_non_blocking);
766}
767
768/*---------------------------------------------------------------------------*/
769/*---------------------------------------------------------------------------*/
770
771auto SharedMemoryMessageQueue::
772addReceive(const PointToPointMessageInfo& message, ReceiveBufferInfo buf) -> Request
773{
774 auto* sq = _getSourceSubQueue(message);
775 return _request(sq->addReceive(_getNextRequestId(), message, buf));
776}
777
778/*---------------------------------------------------------------------------*/
779/*---------------------------------------------------------------------------*/
780
781auto SharedMemoryMessageQueue::
782addSend(const PointToPointMessageInfo& message, SendBufferInfo buf) -> Request
783{
784 auto* sq = _getDestinationSubQueue(message);
785 return _request(sq->addSend(_getNextRequestId(), message, buf));
786}
787
788/*---------------------------------------------------------------------------*/
789/*---------------------------------------------------------------------------*/
790
791auto SharedMemoryMessageQueue::
792probe(const MP::PointToPointMessageInfo& message) -> MessageId
793{
794 auto* sq = _getSourceSubQueue(message);
795 return sq->probe(message);
796}
797
798/*---------------------------------------------------------------------------*/
799/*---------------------------------------------------------------------------*/
800
801auto SharedMemoryMessageQueue::
802legacyProbe(const MP::PointToPointMessageInfo& message) -> MessageSourceInfo
803{
804 auto* sq = _getSourceSubQueue(message);
805 return sq->legacyProbe(message);
806}
807
808/*---------------------------------------------------------------------------*/
809/*---------------------------------------------------------------------------*/
810
811void SharedMemoryMessageQueue::
812setTraceMng(Int32 rank, ITraceMng* tm)
813{
814 _getSubQueue(MessageRank(rank))->setTraceMng(tm);
815}
816
817/*---------------------------------------------------------------------------*/
818/*---------------------------------------------------------------------------*/
819
820auto SharedMemoryMessageQueue::
821_request(SharedMemoryMessageRequest* tmr) -> Request
822{
823 return Request(0, this, tmr);
824}
825
826/*---------------------------------------------------------------------------*/
827/*---------------------------------------------------------------------------*/
828
829const String& SharedMemoryMessageRequest::
830queueName() const
831{
832 return m_queue->name();
833}
834
835/*---------------------------------------------------------------------------*/
836/*---------------------------------------------------------------------------*/
837
838} // End namespace Arcane::MessagePassing
839
840/*---------------------------------------------------------------------------*/
841/*---------------------------------------------------------------------------*/
#define ARCANE_THROW(exception_class,...)
Macro for throwing an exception with formatting.
#define ARCANE_FATAL(...)
Macro throwing a FatalErrorException.
#define ARCCORE_FATAL(...)
Macro throwing a FatalErrorException.
Modifiable view of an array of type T.
Base class for 1D data vectors.
Constant view on a contiguous memory region containing fixed-size elements.
Template class for converting a type.
virtual void copy(const ISerializer *from)=0
Copies the data from from into this instance.
static void genericCopy(ConstMemoryView from, MutableMemoryView to)
Generic copy using platform::getDataMemoryRessourceMng().
Asynchronous queue allowing the exchange of information between threads.
Definition IAsyncQueue.h:33
Information for sending/receiving a point-to-point message.
void _cleanupRequestIfDone(SharedMemoryMessageRequest *tmr)
Cleans up the request tmr if it is finished.
SharedMemoryMessageRequest(SubQueue *queue, Int64 request_id, MessageRank orig, MessageRank dest, MessageTag tag, ReceiveBufferInfo buf)
Create a send request.
void copyFromSender(SharedMemoryMessageRequest *sender)
Copies the sender message information into the receive message.
Mutable view on a contiguous memory region containing fixed-size elements.
1D data vector with value semantics (STL style).
Declarations of types and methods used by message exchange mechanisms.
std::int64_t Int64
Signed integer type of 64 bits.
Int32 Integer
Type representing an integer.
std::int32_t Int32
Signed integer type of 32 bits.