TIMPI
Public Member Functions | Static Public Attributes | Private Attributes | Friends | List of all members
TIMPI::Request Class Reference

Encapsulates the MPI_Request. More...

#include <request.h>

Public Member Functions

 Request ()
 
 Request (const request &r)
 
 Request (const Request &other)
 
void cleanup ()
 
Requestoperator= (const Request &other)
 
Requestoperator= (const request &r)
 
 ~Request ()
 
requestget ()
 
const requestget () const
 
Status wait ()
 
bool test ()
 
bool test (status &status)
 
void add_prior_request (const Request &req)
 
void add_post_wait_work (PostWaitWork *work)
 

Static Public Attributes

static const request null_request = MPI_REQUEST_NULL
 

Private Attributes

request _request
 
std::unique_ptr< Request_prior_request
 
std::pair< std::vector< PostWaitWork *>, unsigned int > * post_wait_work
 

Friends

std::size_t waitany (std::vector< Request > &)
 Wait for at least one non-blocking operation to finish. More...
 

Detailed Description

Encapsulates the MPI_Request.

Definition at line 67 of file request.h.

Constructor & Destructor Documentation

◆ Request() [1/3]

TIMPI::Request::Request ( )

Definition at line 48 of file request.C.

Referenced by add_prior_request(), operator=(), and Request().

48  :
50  post_wait_work(nullptr)
51 {}
static const request null_request
Definition: request.h:111
request _request
Definition: request.h:114
std::pair< std::vector< PostWaitWork *>, unsigned int > * post_wait_work
Definition: request.h:124

◆ Request() [2/3]

TIMPI::Request::Request ( const request r)

Definition at line 53 of file request.C.

53  :
54  _request(r),
55  post_wait_work(nullptr)
56 {}
request _request
Definition: request.h:114
std::pair< std::vector< PostWaitWork *>, unsigned int > * post_wait_work
Definition: request.h:124

◆ Request() [3/3]

TIMPI::Request::Request ( const Request other)

Definition at line 58 of file request.C.

References _prior_request, post_wait_work, and Request().

58  :
59  _request(other._request),
60  post_wait_work(other.post_wait_work)
61 {
62  if (other._prior_request.get())
63  _prior_request = std::unique_ptr<Request>
64  (new Request(*other._prior_request.get()));
65 
66  // operator= should behave like a shared pointer
67  if (post_wait_work)
68  post_wait_work->second++;
69 }
std::unique_ptr< Request > _prior_request
Definition: request.h:116
request _request
Definition: request.h:114
std::pair< std::vector< PostWaitWork *>, unsigned int > * post_wait_work
Definition: request.h:124

◆ ~Request()

TIMPI::Request::~Request ( )

Definition at line 117 of file request.C.

References cleanup().

117  {
118  this->cleanup();
119 }
void cleanup()
Definition: request.C:71

Member Function Documentation

◆ add_post_wait_work()

void TIMPI::Request::add_post_wait_work ( PostWaitWork work)

Definition at line 204 of file request.C.

References post_wait_work.

Referenced by TIMPI::Communicator::nonblocking_receive_packed_range(), TIMPI::Communicator::nonblocking_send_packed_range(), TIMPI::Communicator::possibly_receive(), TIMPI::Communicator::possibly_receive_packed_range(), TIMPI::Communicator::receive(), TIMPI::Communicator::send(), and TIMPI::Communicator::send_packed_range().

205 {
206  if (!post_wait_work)
207  post_wait_work = new
208  std::pair<std::vector <PostWaitWork * >, unsigned int>
209  (std::vector <PostWaitWork * >(), 1);
210  post_wait_work->first.push_back(work);
211 }
std::pair< std::vector< PostWaitWork *>, unsigned int > * post_wait_work
Definition: request.h:124

◆ add_prior_request()

void TIMPI::Request::add_prior_request ( const Request req)

Definition at line 190 of file request.C.

References _prior_request, and Request().

Referenced by TIMPI::Communicator::send_packed_range().

191 {
192  // We're making a chain of prior requests, not a tree
193  timpi_assert(!req._prior_request.get());
194 
195  Request * new_prior_req = new Request(req);
196 
197  // new_prior_req takes ownership of our existing _prior_request
198  new_prior_req->_prior_request.reset(this->_prior_request.release());
199 
200  // Our _prior_request now manages the new resource we just set up
201  this->_prior_request.reset(new_prior_req);
202 }
std::unique_ptr< Request > _prior_request
Definition: request.h:116

◆ cleanup()

void TIMPI::Request::cleanup ( )

Definition at line 71 of file request.C.

References post_wait_work.

Referenced by operator=(), and ~Request().

72 {
73  if (post_wait_work)
74  {
75  // Decrement the use count
76  post_wait_work->second--;
77 
78  if (!post_wait_work->second)
79  {
80 #ifdef DEBUG
81  // If we're done using this request, then we'd better have
82  // done the work we waited for
83  for (const auto & item : post_wait_work->first)
84  timpi_assert(!item);
85 #endif
86  delete post_wait_work;
87  post_wait_work = nullptr;
88  }
89  }
90 }
std::pair< std::vector< PostWaitWork *>, unsigned int > * post_wait_work
Definition: request.h:124

◆ get() [1/2]

request* TIMPI::Request::get ( )
inline

◆ get() [2/2]

const request* TIMPI::Request::get ( ) const
inline

Definition at line 86 of file request.h.

References _request.

86 { return &_request; }
request _request
Definition: request.h:114

◆ operator=() [1/2]

Request & TIMPI::Request::operator= ( const Request other)

Definition at line 92 of file request.C.

References _prior_request, _request, cleanup(), post_wait_work, and Request().

93 {
94  this->cleanup();
95  _request = other._request;
96  post_wait_work = other.post_wait_work;
97 
98  if (other._prior_request.get())
99  _prior_request = std::unique_ptr<Request>
100  (new Request(*other._prior_request.get()));
101 
102  // operator= should behave like a shared pointer
103  if (post_wait_work)
104  post_wait_work->second++;
105 
106  return *this;
107 }
std::unique_ptr< Request > _prior_request
Definition: request.h:116
void cleanup()
Definition: request.C:71
request _request
Definition: request.h:114
std::pair< std::vector< PostWaitWork *>, unsigned int > * post_wait_work
Definition: request.h:124

◆ operator=() [2/2]

Request & TIMPI::Request::operator= ( const request r)

Definition at line 109 of file request.C.

References _request, cleanup(), and post_wait_work.

110 {
111  this->cleanup();
112  _request = r;
113  post_wait_work = nullptr;
114  return *this;
115 }
void cleanup()
Definition: request.C:71
request _request
Definition: request.h:114
std::pair< std::vector< PostWaitWork *>, unsigned int > * post_wait_work
Definition: request.h:124

◆ test() [1/2]

bool TIMPI::Request::test ( )

Definition at line 153 of file request.C.

References _request, and null_request.

Referenced by TIMPI::detail::push_parallel_nbx_helper(), and testNonblockingTest().

154 {
155 #ifdef TIMPI_HAVE_MPI
156  int val=0;
157 
158  timpi_call_mpi
159  (MPI_Test (&_request, &val, MPI_STATUS_IGNORE));
160 
161  if (val)
162  {
163  timpi_assert (_request == null_request);
164  timpi_assert_equal_to (val, 1);
165  }
166 
167  return val;
168 #else
169  return true;
170 #endif
171 }
static const request null_request
Definition: request.h:111
request _request
Definition: request.h:114

◆ test() [2/2]

bool TIMPI::Request::test ( status status)

Definition at line 174 of file request.C.

References _request.

175 {
176  int val=0;
177 
178  timpi_call_mpi
179  (MPI_Test (&_request, &val, &stat));
180 
181  return val;
182 }
request _request
Definition: request.h:114

◆ wait()

Status TIMPI::Request::wait ( )

Definition at line 121 of file request.C.

References _prior_request, _request, and post_wait_work.

Referenced by TIMPI::detail::push_parallel_nbx_helper(), TIMPI::push_parallel_packed_range(), TIMPI::Communicator::send_receive_packed_range(), testNonblockingMax(), testNonblockingMin(), and TIMPI::wait().

122 {
123  TIMPI_LOG_SCOPE("wait()", "Request");
124 
125  if (_prior_request.get())
126  {
127  _prior_request->wait();
128  _prior_request.reset(nullptr);
129  }
130 
131  Status stat {};
132 #ifdef TIMPI_HAVE_MPI
133  timpi_call_mpi
134  (MPI_Wait (&_request, stat.get()));
135 #endif
136  if (post_wait_work)
137  {
138  for (auto & item : post_wait_work->first)
139  {
140  // The user should never try to give us non-existent work or try
141  // to wait() twice.
142  timpi_assert (item);
143  item->run();
144  delete item;
145  item = nullptr;
146  }
147  post_wait_work->first.clear();
148  }
149 
150  return stat;
151 }
std::unique_ptr< Request > _prior_request
Definition: request.h:116
request _request
Definition: request.h:114
std::pair< std::vector< PostWaitWork *>, unsigned int > * post_wait_work
Definition: request.h:124

Friends And Related Function Documentation

◆ waitany

std::size_t waitany ( std::vector< Request > &  r)
friend

Wait for at least one non-blocking operation to finish.

Return the index of the request which completed.

Definition at line 219 of file request.C.

220 {
221  timpi_assert(!r.empty());
222 
223  int r_size = cast_int<int>(r.size());
224  std::vector<request> raw(r_size);
225  int non_null = r_size;
226  for (int i=0; i != r_size; ++i)
227  {
228  Request * root = &r[i];
229  // If we have prior requests, we need to complete the first one
230  // first
231  while (root->_prior_request.get())
232  root = root->_prior_request.get();
233  raw[i] = *root->get();
234 
235  if (raw[i] != Request::null_request)
236  non_null = std::min(non_null,i);
237  }
238 
239  if (non_null == r_size)
240  return std::size_t(-1);
241 
242  int index = non_null;
243 
244 #ifdef TIMPI_HAVE_MPI
245  bool only_priors_completed = false;
246  Request * next;
247 
248  do
249  {
250  timpi_call_mpi
251  (MPI_Waitany(r_size, raw.data(), &index, MPI_STATUS_IGNORE));
252 
253  timpi_assert_not_equal_to(index, MPI_UNDEFINED);
254 
255  timpi_assert_less(index, r_size);
256 
257  Request * completed = &r[index];
258  next = completed;
259 
260  // If we completed a prior request, we're not really done yet,
261  // so find the next in that line to try again.
262  while (completed->_prior_request.get())
263  {
264  only_priors_completed = true;
265  next = completed;
266  completed = completed->_prior_request.get();
267  }
268 
269  // MPI sets a completed MPI_Request to MPI_REQUEST_NULL; we want
270  // to preserve that
271  completed->_request = raw[index];
272 
273  // Do any post-wait work for the completed request
274  if (completed->post_wait_work)
275  for (auto & item : completed->post_wait_work->first)
276  {
277  // The user should never try to give us non-existent work or try
278  // to wait() twice.
279  timpi_assert (item);
280  item->run();
281  delete item;
282  item = nullptr;
283  }
284 
285  next->_prior_request.reset(nullptr);
286  raw[index] = *next->get();
287 
288  } while(only_priors_completed);
289 #else
290  r[index]._request = Request::null_request;
291 #endif
292 
293  return index;
294 }
static const request null_request
Definition: request.h:111

Member Data Documentation

◆ _prior_request

std::unique_ptr<Request> TIMPI::Request::_prior_request
private

Definition at line 116 of file request.h.

Referenced by add_prior_request(), operator=(), Request(), wait(), and TIMPI::waitany().

◆ _request

request TIMPI::Request::_request
private

Definition at line 114 of file request.h.

Referenced by get(), operator=(), test(), wait(), and TIMPI::waitany().

◆ null_request

const request TIMPI::Request::null_request = MPI_REQUEST_NULL
static

◆ post_wait_work

std::pair<std::vector <PostWaitWork * >, unsigned int>* TIMPI::Request::post_wait_work
private

Definition at line 124 of file request.h.

Referenced by add_post_wait_work(), cleanup(), operator=(), Request(), wait(), and TIMPI::waitany().


The documentation for this class was generated from the following files: