libMesh::Parallel::Request Class Reference

#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)
 

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 > &)
 

Detailed Description

Encapsulates the MPI_Request

Definition at line 63 of file request.h.

Constructor & Destructor Documentation

◆ Request() [1/3]

libMesh::Parallel::Request::Request ( )

Definition at line 44 of file request.C.

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

44  :
45 #ifdef LIBMESH_HAVE_MPI
46  _request(MPI_REQUEST_NULL),
47 #else
48  _request(),
49 #endif
50  post_wait_work(nullptr)
51 {}
std::pair< std::vector< PostWaitWork *>, unsigned int > * post_wait_work
Definition: request.h:118

◆ Request() [2/3]

libMesh::Parallel::Request::Request ( const request r)

Definition at line 53 of file request.C.

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

◆ Request() [3/3]

libMesh::Parallel::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::pair< std::vector< PostWaitWork *>, unsigned int > * post_wait_work
Definition: request.h:118
std::unique_ptr< Request > _prior_request
Definition: request.h:110

◆ ~Request()

libMesh::Parallel::Request::~Request ( )

Definition at line 117 of file request.C.

References cleanup().

117  {
118  this->cleanup();
119 }

Member Function Documentation

◆ add_post_wait_work()

void libMesh::Parallel::Request::add_post_wait_work ( PostWaitWork work)

Definition at line 204 of file request.C.

References post_wait_work.

Referenced by libMesh::Parallel::Communicator::nonblocking_receive_packed_range(), libMesh::Parallel::Communicator::nonblocking_send_packed_range(), libMesh::Parallel::Communicator::receive(), libMesh::Parallel::Communicator::send(), and libMesh::Parallel::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:118

◆ add_prior_request()

void libMesh::Parallel::Request::add_prior_request ( const Request req)

Definition at line 190 of file request.C.

References _prior_request, and Request().

Referenced by libMesh::Parallel::Communicator::send_packed_range().

191 {
192  // We're making a chain of prior requests, not a tree
193  libmesh_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:110

◆ cleanup()

void libMesh::Parallel::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  libmesh_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:118

◆ get() [1/2]

request* libMesh::Parallel::Request::get ( )
inline

◆ get() [2/2]

const request* libMesh::Parallel::Request::get ( ) const
inline

Definition at line 82 of file request.h.

References _request.

82 { return &_request; }

◆ operator=() [1/2]

Request & libMesh::Parallel::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::pair< std::vector< PostWaitWork *>, unsigned int > * post_wait_work
Definition: request.h:118
std::unique_ptr< Request > _prior_request
Definition: request.h:110

◆ operator=() [2/2]

Request & libMesh::Parallel::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 }
std::pair< std::vector< PostWaitWork *>, unsigned int > * post_wait_work
Definition: request.h:118

◆ test() [1/2]

bool libMesh::Parallel::Request::test ( )

Definition at line 153 of file request.C.

References _request.

154 {
155 #ifdef LIBMESH_HAVE_MPI
156  int val=0;
157 
158  libmesh_call_mpi
159  (MPI_Test (&_request, &val, MPI_STATUS_IGNORE));
160 
161  if (val)
162  {
163  libmesh_assert (_request == MPI_REQUEST_NULL);
164  libmesh_assert_equal_to (val, 1);
165  }
166 
167  return val;
168 #else
169  return true;
170 #endif
171 }

◆ test() [2/2]

bool libMesh::Parallel::Request::test ( status status)

Definition at line 174 of file request.C.

References _request.

175 {
176  int val=0;
177 
178  libmesh_call_mpi
179  (MPI_Test (&_request, &val, &stat));
180 
181  return val;
182 }

◆ wait()

Status libMesh::Parallel::Request::wait ( )

Definition at line 121 of file request.C.

References _prior_request, _request, libMesh::Parallel::Status::get(), and post_wait_work.

Referenced by libMesh::Parallel::Communicator::send_receive_packed_range(), and libMesh::Parallel::wait().

122 {
123  LOG_SCOPE("wait()", "Parallel::Request");
124 
125  if (_prior_request.get())
126  {
127  _prior_request->wait();
128  _prior_request.reset(nullptr);
129  }
130 
131  Status stat;
132 #ifdef LIBMESH_HAVE_MPI
133  libmesh_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  libmesh_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::pair< std::vector< PostWaitWork *>, unsigned int > * post_wait_work
Definition: request.h:118
std::unique_ptr< Request > _prior_request
Definition: request.h:110

Friends And Related Function Documentation

◆ waitany

std::size_t waitany ( std::vector< Request > &  )
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  libmesh_assert(!r.empty());
222 
223  int index = 0;
224  int r_size = cast_int<int>(r.size());
225  std::vector<request> raw(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 
236  bool only_priors_completed = false;
237 
238  Request * next;
239 
240  do
241  {
242 #ifdef LIBMESH_HAVE_MPI
243  libmesh_call_mpi
244  (MPI_Waitany(r_size, raw.data(), &index, MPI_STATUS_IGNORE));
245 #endif
246 
247  Request * completed = &r[index];
248  next = completed;
249 
250  // If we completed a prior request, we're not really done yet,
251  // so find the next in that line to try again.
252  while (completed->_prior_request.get())
253  {
254  only_priors_completed = true;
255  next = completed;
256  completed = completed->_prior_request.get();
257  }
258 
259  // Do any post-wait work for the completed request
260  if (completed->post_wait_work)
261  for (auto & item : completed->post_wait_work->first)
262  {
263  // The user should never try to give us non-existent work or try
264  // to wait() twice.
265  libmesh_assert (item);
266  item->run();
267  delete item;
268  item = nullptr;
269  }
270 
271  next->_prior_request.reset(nullptr);
272  raw[index] = *next->get();
273 
274  } while(only_priors_completed);
275 
276  return index;
277 }
static const unsigned int next[3]

Member Data Documentation

◆ _prior_request

std::unique_ptr<Request> libMesh::Parallel::Request::_prior_request
private

Definition at line 110 of file request.h.

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

◆ _request

request libMesh::Parallel::Request::_request
private

Definition at line 108 of file request.h.

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

◆ post_wait_work

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

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