diff options
author | Lorry Tar Creator <lorry-tar-importer@baserock.org> | 2013-06-25 22:59:01 +0000 |
---|---|---|
committer | <> | 2013-09-27 11:49:28 +0000 |
commit | 8c4528713d907ee2cfd3bfcbbad272c749867f84 (patch) | |
tree | c09e2ce80f47b90c85cc720f5139089ad9c8cfff /libs/mpi/src/request.cpp | |
download | boost-tarball-baserock/morph.tar.gz |
Imported from /home/lorry/working-area/delta_boost-tarball/boost_1_54_0.tar.bz2.boost_1_54_0baserock/morph
Diffstat (limited to 'libs/mpi/src/request.cpp')
-rw-r--r-- | libs/mpi/src/request.cpp | 120 |
1 files changed, 120 insertions, 0 deletions
diff --git a/libs/mpi/src/request.cpp b/libs/mpi/src/request.cpp new file mode 100644 index 000000000..9bc842f2e --- /dev/null +++ b/libs/mpi/src/request.cpp @@ -0,0 +1,120 @@ +// Copyright (C) 2006 Douglas Gregor. + +// Use, modification and distribution is subject to the Boost Software +// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +#include <boost/mpi/request.hpp> +#include <boost/mpi/status.hpp> + +namespace boost { namespace mpi { + +/*************************************************************************** + * request * + ***************************************************************************/ +request::request() + : m_handler(0), m_data() +{ + m_requests[0] = MPI_REQUEST_NULL; + m_requests[1] = MPI_REQUEST_NULL; +} + +status request::wait() +{ + if (m_handler) { + // This request is a receive for a serialized type. Use the + // handler to wait for completion. + return *m_handler(this, ra_wait); + } else if (m_requests[1] == MPI_REQUEST_NULL) { + // This request is either a send or a receive for a type with an + // associated MPI datatype, or a serialized datatype that has been + // packed into a single message. Just wait on the one receive/send + // and return the status to the user. + status result; + BOOST_MPI_CHECK_RESULT(MPI_Wait, (&m_requests[0], &result.m_status)); + return result; + } else { + // This request is a send of a serialized type, broken into two + // separate messages. Complete both sends at once. + MPI_Status stats[2]; + int error_code = MPI_Waitall(2, m_requests, stats); + if (error_code == MPI_ERR_IN_STATUS) { + // Dig out which status structure has the error, and use that + // one when throwing the exception. + if (stats[0].MPI_ERROR == MPI_SUCCESS + || stats[0].MPI_ERROR == MPI_ERR_PENDING) + boost::throw_exception(exception("MPI_Waitall", stats[1].MPI_ERROR)); + else + boost::throw_exception(exception("MPI_Waitall", stats[0].MPI_ERROR)); + } else if (error_code != MPI_SUCCESS) { + // There was an error somewhere in the MPI_Waitall call; throw + // an exception for it. + boost::throw_exception(exception("MPI_Waitall", error_code)); + } + + // No errors. Returns the first status structure. + status result; + result.m_status = stats[0]; + return result; + } +} + +optional<status> request::test() +{ + if (m_handler) { + // This request is a receive for a serialized type. Use the + // handler to test for completion. + return m_handler(this, ra_test); + } else if (m_requests[1] == MPI_REQUEST_NULL) { + // This request is either a send or a receive for a type with an + // associated MPI datatype, or a serialized datatype that has been + // packed into a single message. Just test the one receive/send + // and return the status to the user if it has completed. + status result; + int flag = 0; + BOOST_MPI_CHECK_RESULT(MPI_Test, + (&m_requests[0], &flag, &result.m_status)); + return flag != 0? optional<status>(result) : optional<status>(); + } else { + // This request is a send of a serialized type, broken into two + // separate messages. We only get a result if both complete. + MPI_Status stats[2]; + int flag = 0; + int error_code = MPI_Testall(2, m_requests, &flag, stats); + if (error_code == MPI_ERR_IN_STATUS) { + // Dig out which status structure has the error, and use that + // one when throwing the exception. + if (stats[0].MPI_ERROR == MPI_SUCCESS + || stats[0].MPI_ERROR == MPI_ERR_PENDING) + boost::throw_exception(exception("MPI_Testall", stats[1].MPI_ERROR)); + else + boost::throw_exception(exception("MPI_Testall", stats[0].MPI_ERROR)); + } else if (error_code != MPI_SUCCESS) { + // There was an error somewhere in the MPI_Testall call; throw + // an exception for it. + boost::throw_exception(exception("MPI_Testall", error_code)); + } + + // No errors. Returns the second status structure if the send has + // completed. + if (flag != 0) { + status result; + result.m_status = stats[1]; + return result; + } else { + return optional<status>(); + } + } +} + +void request::cancel() +{ + if (m_handler) { + m_handler(this, ra_cancel); + } else { + BOOST_MPI_CHECK_RESULT(MPI_Cancel, (&m_requests[0])); + if (m_requests[1] != MPI_REQUEST_NULL) + BOOST_MPI_CHECK_RESULT(MPI_Cancel, (&m_requests[1])); + } +} + +} } // end namespace boost::mpi |