Fenix @develop
 
Loading...
Searching...
No Matches
request.hpp
1#ifndef FENIX_TASKS_REQUEST_HPP
2#define FENIX_TASKS_REQUEST_HPP
3
4#include <coroutine>
5#include <exception>
6#include <cassert>
7
8#include <mpi.h>
9
10#include "subtask.hpp"
11#include "fenix/mpi_util.hpp"
12
13namespace fenix::tasks {
14
15using util::Status;
16
17// Note that this 'takes ownership' of the request - if RequestBase is destroyed
18// before completing, it frees the MPI_Request to ensure proper cleanup if a
19// Task is destroyed before completing.
20class Request {
21 public:
22 Request(MPI_Request* r) : request(r) {};
23
24 Request() = default;
25 Request(const Request&) = delete;
26 Request(Request&& r) { *this = std::move(r); }
27 Request& operator=(MPI_Request* r) { return *this = Request(r); }
28 Request& operator=(Request&& r) {
29 mpi_free();
30 *this = r;
31 Request tmp{};
32 r = tmp;
33 return *this;
34 }
35
36 // TODO: this turned out buggy, figure out why
37 ~Request() { /*mpi_free();*/ }
38
39 bool operator==(const MPI_Request* r) const { return r == request; }
40
41 bool is_complete() {
42 return complete || request == nullptr || *request == MPI_REQUEST_NULL;
43 }
44
45 bool test() {
46 if (!is_complete()) {
47 ret = MPI_Test(request, &complete, ret);
48 if (ret != MPI_SUCCESS) complete = true;
49 }
50 return is_complete();
51 }
52 void wait() {
53 if (!is_complete()) {
54 ret = MPI_Wait(request, ret);
55 complete = true;
56 }
57 }
58 void mpi_free() {
59 if (!is_complete()) MPI_Request_free(request);
60 }
61
62 bool done() { return test(); }
63 void resume() { test(); }
64 auto result() {
65 assert(done());
66 return ret;
67 }
68
69 private:
70 Request& operator=(const Request& r) {
71 request = r.request;
72 ret = r.ret;
73 complete = r.complete;
74 return *this;
75 }
76
77 MPI_Request* request = nullptr;
78 Status ret;
79 int complete = false;
80};
81
82} // namespace fenix::tasks
83
84#endif //FENIX_TASKS_REQUEST_HPP
Definition request.hpp:20
Definition mpi_util.hpp:115