1use std::marker::PhantomData;
6
7use crate::datatype::{Buffer, BufferMut, DatatypeRef, Equivalence};
8use crate::request::{Request, Scope};
9use crate::topology::CommData;
10use crate::transport::{self, ANY_SOURCE, ANY_TAG};
11use crate::{Count, Rank, Tag};
12
13pub const DEFAULT_TAG: Tag = 0;
15
16pub(crate) fn elem_from_bytes<T: Equivalence>(bytes: &[u8]) -> T {
19 assert!(
20 bytes.len() >= std::mem::size_of::<T>(),
21 "received message smaller than expected scalar"
22 );
23 unsafe { std::ptr::read_unaligned(bytes.as_ptr() as *const T) }
26}
27
28pub(crate) fn vec_from_bytes<T: Equivalence>(bytes: &[u8]) -> Vec<T> {
29 let size = std::mem::size_of::<T>();
30 let count = bytes.len().checked_div(size).unwrap_or(0);
31 let mut v: Vec<T> = Vec::with_capacity(count);
32 unsafe {
35 std::ptr::copy_nonoverlapping(bytes.as_ptr(), v.as_mut_ptr() as *mut u8, count * size);
36 v.set_len(count);
37 }
38 v
39}
40
41pub(crate) fn copy_into_buffer<Buf: BufferMut + ?Sized>(buf: &mut Buf, bytes: &[u8]) {
42 buf.scatter_from(bytes);
45}
46
47#[derive(Copy, Clone, Debug, PartialEq, Eq)]
49pub struct Status {
50 source: Rank,
51 tag: Tag,
52 count: Count,
53 byte_len: usize,
54}
55
56impl Status {
57 pub(crate) fn new(source: Rank, tag: Tag, count: Count, byte_len: usize) -> Status {
58 Status {
59 source,
60 tag,
61 count,
62 byte_len,
63 }
64 }
65
66 pub fn source_rank(&self) -> Rank {
68 self.source
69 }
70
71 pub fn tag(&self) -> Tag {
73 self.tag
74 }
75
76 pub fn count(&self, dt: DatatypeRef) -> Count {
78 self.byte_len.checked_div(dt.size).unwrap_or(0) as Count
79 }
80
81 pub fn is_cancelled(&self) -> bool {
84 false
85 }
86
87 pub fn is_canceled(&self) -> bool {
89 false
90 }
91}
92
93pub struct Message {
97 source: Rank,
98 tag: Tag,
99 count: Count,
100 payload: Vec<u8>,
101}
102
103impl Message {
104 pub fn matched_receive_vec<Msg: Equivalence>(self) -> (Vec<Msg>, Status) {
107 let status = Status::new(self.source, self.tag, self.count, self.payload.len());
108 (vec_from_bytes::<Msg>(&self.payload), status)
109 }
110
111 pub fn matched_receive_into<Buf: BufferMut + ?Sized>(self, buf: &mut Buf) -> Status {
113 let status = Status::new(self.source, self.tag, self.count, self.payload.len());
114 copy_into_buffer(buf, &self.payload);
115 status
116 }
117}
118
119pub trait Source {
122 #[doc(hidden)]
124 fn src_comm(&self) -> &CommData;
125
126 fn source_rank(&self) -> Rank;
128
129 fn receive<Msg: Equivalence>(&self) -> (Msg, Status) {
131 self.receive_with_tag(ANY_TAG)
132 }
133
134 fn receive_with_tag<Msg: Equivalence>(&self, tag: Tag) -> (Msg, Status) {
136 let comm = self.src_comm();
137 let (src, t, count, _dt, payload) =
138 transport::runtime().recv(comm.context, self.source_rank(), tag);
139 let val = elem_from_bytes::<Msg>(&payload);
140 (val, Status::new(src, t, count as Count, payload.len()))
141 }
142
143 fn receive_vec<Msg: Equivalence>(&self) -> (Vec<Msg>, Status) {
145 self.receive_vec_with_tag(ANY_TAG)
146 }
147
148 fn receive_vec_with_tag<Msg: Equivalence>(&self, tag: Tag) -> (Vec<Msg>, Status) {
150 let comm = self.src_comm();
151 let (src, t, count, _dt, payload) =
152 transport::runtime().recv(comm.context, self.source_rank(), tag);
153 let v = vec_from_bytes::<Msg>(&payload);
154 (v, Status::new(src, t, count as Count, payload.len()))
155 }
156
157 fn receive_into<Buf: BufferMut + ?Sized>(&self, buf: &mut Buf) -> Status {
159 self.receive_into_with_tag(buf, ANY_TAG)
160 }
161
162 fn receive_into_with_tag<Buf: BufferMut + ?Sized>(&self, buf: &mut Buf, tag: Tag) -> Status {
164 let comm = self.src_comm();
165 let (src, t, count, _dt, payload) =
166 transport::runtime().recv(comm.context, self.source_rank(), tag);
167 copy_into_buffer(buf, &payload);
168 Status::new(src, t, count as Count, payload.len())
169 }
170
171 fn probe(&self) -> Status {
174 self.probe_with_tag(ANY_TAG)
175 }
176
177 fn probe_with_tag(&self, tag: Tag) -> Status {
179 let comm = self.src_comm();
180 let (src, t, count, _dt, len) =
181 transport::runtime().probe_blocking(comm.context, self.source_rank(), tag);
182 Status::new(src, t, count as Count, len)
183 }
184
185 fn immediate_probe(&self) -> Option<Status> {
187 self.immediate_probe_with_tag(ANY_TAG)
188 }
189
190 fn immediate_probe_with_tag(&self, tag: Tag) -> Option<Status> {
192 let comm = self.src_comm();
193 transport::runtime()
194 .probe(comm.context, self.source_rank(), tag)
195 .map(|(src, t, count, _dt, len)| Status::new(src, t, count as Count, len))
196 }
197
198 fn matched_probe(&self) -> (Message, Status) {
201 self.matched_probe_with_tag(ANY_TAG)
202 }
203
204 fn matched_probe_with_tag(&self, tag: Tag) -> (Message, Status) {
206 let comm = self.src_comm();
207 let (src, t, count, _dt, payload) =
208 transport::runtime().recv(comm.context, self.source_rank(), tag);
209 let status = Status::new(src, t, count as Count, payload.len());
210 (
211 Message {
212 source: src,
213 tag: t,
214 count: count as Count,
215 payload,
216 },
217 status,
218 )
219 }
220
221 fn immediate_matched_probe(&self) -> Option<(Message, Status)> {
223 self.immediate_matched_probe_with_tag(ANY_TAG)
224 }
225
226 fn immediate_matched_probe_with_tag(&self, tag: Tag) -> Option<(Message, Status)> {
228 if self.immediate_probe_with_tag(tag).is_some() {
229 Some(self.matched_probe_with_tag(tag))
230 } else {
231 None
232 }
233 }
234
235 fn immediate_receive<Msg: Equivalence>(&self) -> ReceiveFuture<Msg> {
237 self.immediate_receive_with_tag(ANY_TAG)
238 }
239
240 fn immediate_receive_with_tag<Msg: Equivalence>(&self, tag: Tag) -> ReceiveFuture<Msg> {
242 let comm = self.src_comm();
243 ReceiveFuture {
244 ctx: comm.context,
245 source: self.source_rank(),
246 tag,
247 _p: PhantomData,
248 }
249 }
250
251 fn immediate_receive_into<'a, Sc, Buf>(
254 &self,
255 scope: Sc,
256 buf: &'a mut Buf,
257 ) -> Request<'a, Buf, Sc>
258 where
259 Buf: 'a + BufferMut + ?Sized,
260 Sc: Scope<'a>,
261 {
262 self.immediate_receive_into_with_tag(scope, buf, ANY_TAG)
263 }
264
265 fn immediate_receive_into_with_tag<'a, Sc, Buf>(
267 &self,
268 scope: Sc,
269 buf: &'a mut Buf,
270 tag: Tag,
271 ) -> Request<'a, Buf, Sc>
272 where
273 Buf: 'a + BufferMut + ?Sized,
274 Sc: Scope<'a>,
275 {
276 let ctx = self.src_comm().context;
277 let source = self.source_rank();
278 let bytes = buf.as_bytes_mut();
279 let ptr = bytes.as_mut_ptr();
280 let len = bytes.len();
281 Request::pending_recv(scope, ptr, len, ctx, source, tag)
282 }
283
284 fn receive_init<'a, Buf: BufferMut + ?Sized>(
287 &self,
288 buf: &'a mut Buf,
289 ) -> crate::request::PersistentRequest<'a> {
290 let ctx = self.src_comm().context;
291 let source = self.source_rank();
292 let bytes = buf.as_bytes_mut();
293 let ptr = bytes.as_mut_ptr();
294 let len = bytes.len();
295 crate::request::PersistentRequest::new_recv(ctx, source, DEFAULT_TAG, ptr, len)
296 }
297}
298
299pub trait Destination {
301 #[doc(hidden)]
303 fn dst_comm(&self) -> &CommData;
304
305 fn destination_rank(&self) -> Rank;
307
308 #[doc(hidden)]
309 fn do_try_send<Buf: Buffer + ?Sized>(
310 &self,
311 buf: &Buf,
312 tag: Tag,
313 ) -> Result<(), crate::MpiError> {
314 let comm = self.dst_comm();
315 let dt = buf.as_datatype();
316 transport::runtime()
317 .send(
318 comm.context,
319 comm.rank,
320 comm.world_rank(self.destination_rank()),
321 tag,
322 buf.count() as u64,
323 dt.id,
324 buf.as_bytes(),
325 )
326 .map_err(|e| crate::MpiError::Other(format!("send failed: {e}")))
327 }
328
329 #[doc(hidden)]
330 fn do_send<Buf: Buffer + ?Sized>(&self, buf: &Buf, tag: Tag) {
331 self.do_try_send(buf, tag).expect("MPI send failed");
332 }
333
334 fn send<Buf: Buffer + ?Sized>(&self, buf: &Buf) {
336 self.do_send(buf, DEFAULT_TAG);
337 }
338
339 fn send_with_tag<Buf: Buffer + ?Sized>(&self, buf: &Buf, tag: Tag) {
341 self.do_send(buf, tag);
342 }
343
344 fn try_send<Buf: Buffer + ?Sized>(&self, buf: &Buf) -> Result<(), crate::MpiError> {
349 self.do_try_send(buf, DEFAULT_TAG)
350 }
351
352 fn try_send_with_tag<Buf: Buffer + ?Sized>(
354 &self,
355 buf: &Buf,
356 tag: Tag,
357 ) -> Result<(), crate::MpiError> {
358 self.do_try_send(buf, tag)
359 }
360
361 fn buffered_send<Buf: Buffer + ?Sized>(&self, buf: &Buf) {
364 self.do_send(buf, DEFAULT_TAG);
365 }
366
367 fn buffered_send_with_tag<Buf: Buffer + ?Sized>(&self, buf: &Buf, tag: Tag) {
369 self.do_send(buf, tag);
370 }
371
372 fn synchronous_send<Buf: Buffer + ?Sized>(&self, buf: &Buf) {
374 self.do_send(buf, DEFAULT_TAG);
375 }
376
377 fn synchronous_send_with_tag<Buf: Buffer + ?Sized>(&self, buf: &Buf, tag: Tag) {
379 self.do_send(buf, tag);
380 }
381
382 unsafe fn ready_send<Buf: Buffer + ?Sized>(&self, buf: &Buf) {
390 self.do_send(buf, DEFAULT_TAG);
391 }
392
393 unsafe fn ready_send_with_tag<Buf: Buffer + ?Sized>(&self, buf: &Buf, tag: Tag) {
399 self.do_send(buf, tag);
400 }
401
402 fn immediate_send<'a, Sc, Buf>(&self, scope: Sc, buf: &'a Buf) -> Request<'a, Buf, Sc>
404 where
405 Buf: 'a + Buffer + ?Sized,
406 Sc: Scope<'a>,
407 {
408 self.immediate_send_with_tag(scope, buf, DEFAULT_TAG)
409 }
410
411 fn immediate_send_with_tag<'a, Sc, Buf>(
413 &self,
414 scope: Sc,
415 buf: &'a Buf,
416 tag: Tag,
417 ) -> Request<'a, Buf, Sc>
418 where
419 Buf: 'a + Buffer + ?Sized,
420 Sc: Scope<'a>,
421 {
422 self.do_send(buf, tag);
428 Request::completed(scope)
429 }
430
431 fn immediate_buffered_send<'a, Sc, Buf>(&self, scope: Sc, buf: &'a Buf) -> Request<'a, Buf, Sc>
433 where
434 Buf: 'a + Buffer + ?Sized,
435 Sc: Scope<'a>,
436 {
437 self.immediate_send_with_tag(scope, buf, DEFAULT_TAG)
438 }
439
440 fn immediate_synchronous_send<'a, Sc, Buf>(
442 &self,
443 scope: Sc,
444 buf: &'a Buf,
445 ) -> Request<'a, Buf, Sc>
446 where
447 Buf: 'a + Buffer + ?Sized,
448 Sc: Scope<'a>,
449 {
450 self.immediate_send_with_tag(scope, buf, DEFAULT_TAG)
451 }
452
453 fn send_init<'a, Buf: Buffer + ?Sized>(
457 &self,
458 buf: &'a Buf,
459 ) -> crate::request::PersistentRequest<'a> {
460 let comm = self.dst_comm();
461 let bytes = buf.as_bytes();
462 crate::request::PersistentRequest::new_send(
463 comm.context,
464 comm.rank,
465 comm.world_rank(self.destination_rank()),
466 DEFAULT_TAG,
467 buf.as_datatype().id,
468 buf.count() as u64,
469 bytes.as_ptr(),
470 bytes.len(),
471 )
472 }
473}
474
475pub struct ReceiveFuture<T> {
478 ctx: u32,
479 source: Rank,
480 tag: Tag,
481 _p: PhantomData<T>,
482}
483
484impl<T: Equivalence> ReceiveFuture<T> {
485 pub fn get(self) -> (T, Status) {
487 let (src, t, count, _dt, payload) =
488 transport::runtime().recv(self.ctx, self.source, self.tag);
489 (
490 elem_from_bytes::<T>(&payload),
491 Status::new(src, t, count as Count, payload.len()),
492 )
493 }
494}
495
496pub fn send_receive<R, M, D, S>(msg: &M, destination: &D, source: &S) -> (R, Status)
501where
502 M: Equivalence,
503 R: Equivalence,
504 D: Destination,
505 S: Source,
506{
507 destination.send(msg);
508 source.receive::<R>()
509}
510
511pub fn send_receive_into_with_tags<M, D, B, S>(
514 msg: &M,
515 destination: &D,
516 sendtag: Tag,
517 buf: &mut B,
518 source: &S,
519 receivetag: Tag,
520) -> Status
521where
522 M: Buffer + ?Sized,
523 D: Destination,
524 B: BufferMut + ?Sized,
525 S: Source,
526{
527 destination.send_with_tag(msg, sendtag);
528 source.receive_into_with_tag(buf, receivetag)
529}
530
531pub fn send_receive_into<M, D, B, S>(msg: &M, destination: &D, buf: &mut B, source: &S) -> Status
533where
534 M: Buffer + ?Sized,
535 D: Destination,
536 B: BufferMut + ?Sized,
537 S: Source,
538{
539 send_receive_into_with_tags(msg, destination, DEFAULT_TAG, buf, source, ANY_TAG)
540}
541
542pub fn send_receive_replace_into_with_tags<B, D, S>(
545 buf: &mut B,
546 destination: &D,
547 sendtag: Tag,
548 source: &S,
549 receivetag: Tag,
550) -> Status
551where
552 B: Buffer + BufferMut + ?Sized,
553 D: Destination,
554 S: Source,
555{
556 let saved = buf.as_bytes().to_vec();
557 destination.send_with_tag(&saved[..], sendtag);
558 source.receive_into_with_tag(buf, receivetag)
559}
560
561pub fn send_receive_replace_into<B, D, S>(buf: &mut B, destination: &D, source: &S) -> Status
563where
564 B: Buffer + BufferMut + ?Sized,
565 D: Destination,
566 S: Source,
567{
568 send_receive_replace_into_with_tags(buf, destination, DEFAULT_TAG, source, ANY_TAG)
569}
570
571#[derive(Copy, Clone)]
577pub struct Process<'a> {
578 pub(crate) comm: &'a CommData,
579 pub(crate) rank: Rank,
580}
581
582impl<'a> Process<'a> {
583 pub(crate) fn new(comm: &'a CommData, rank: Rank) -> Process<'a> {
584 Process { comm, rank }
585 }
586
587 pub fn rank(&self) -> Rank {
589 self.rank
590 }
591
592 pub fn is_self(&self) -> bool {
594 self.rank == self.comm.rank
595 }
596}
597
598impl Source for Process<'_> {
599 fn src_comm(&self) -> &CommData {
600 self.comm
601 }
602 fn source_rank(&self) -> Rank {
603 self.rank
604 }
605}
606
607impl Destination for Process<'_> {
608 fn dst_comm(&self) -> &CommData {
609 self.comm
610 }
611 fn destination_rank(&self) -> Rank {
612 self.rank
613 }
614}
615
616#[derive(Copy, Clone)]
618pub struct AnyProcess<'a> {
619 comm: &'a CommData,
620}
621
622impl<'a> AnyProcess<'a> {
623 pub(crate) fn new(comm: &'a CommData) -> AnyProcess<'a> {
624 AnyProcess { comm }
625 }
626}
627
628impl Source for AnyProcess<'_> {
629 fn src_comm(&self) -> &CommData {
630 self.comm
631 }
632 fn source_rank(&self) -> Rank {
633 ANY_SOURCE
634 }
635}