From b3a60e947379f201cc82c9105835a4e1cf4f84f0 Mon Sep 17 00:00:00 2001 From: Douglas Gregor Date: Mon, 14 Apr 2008 14:14:53 +0000 Subject: [PATCH] Merge Boost.MPI datatype fixes from the trunk [SVN r44414] --- include/boost/mpi/datatype.hpp | 29 +++++++++-- .../boost/mpi/detail/mpi_datatype_cache.hpp | 45 ++++++----------- src/mpi_datatype_cache.cpp | 49 ++++++++++++++++++- 3 files changed, 87 insertions(+), 36 deletions(-) diff --git a/include/boost/mpi/datatype.hpp b/include/boost/mpi/datatype.hpp index 84b3f78..26008e1 100644 --- a/include/boost/mpi/datatype.hpp +++ b/include/boost/mpi/datatype.hpp @@ -181,7 +181,7 @@ struct is_mpi_datatype template MPI_Datatype get_mpi_datatype(const T& x) { BOOST_MPL_ASSERT((is_mpi_datatype)); - return detail::mpi_datatype_cache.datatype(x); + return detail::mpi_datatype_cache().datatype(x); } // Don't parse this part when we're generating Doxygen documentation. @@ -252,15 +252,34 @@ BOOST_MPI_DATATYPE(std::pair), MPI_SHORT_INT, BOOST_MPI_DATATYPE(std::pair), MPI_2INT, builtin); #undef BOOST_MPI_LIST2 -#if 0 -#ifndef BOOST_NO_INTRINSIC_WCHAR_T +// Define wchar_t specialization of is_mpi_datatype, if possible. +#if !defined(BOOST_NO_INTRINSIC_WCHAR_T) && \ + (defined(MPI_WCHAR) || (defined(MPI_VERSION) && MPI_VERSION >= 2)) BOOST_MPI_DATATYPE(wchar_t, MPI_WCHAR, builtin); #endif -#ifdef BOOST_HAS_LONG_LONG +// Define long long or __int64 specialization of is_mpi_datatype, if possible. +#if defined(BOOST_HAS_LONG_LONG) && \ + (defined(MPI_LONG_LONG_INT) || (defined(MPI_VERSION) && MPI_VERSION >= 2)) BOOST_MPI_DATATYPE(long long, MPI_LONG_LONG_INT, builtin); -BOOST_MPI_DATATYPE(unsigned long long, MPI_UNSIGNED_LONG_LONG, builtin); +#elif defined(BOOST_HAS_MS_INT64) && \ + (defined(MPI_LONG_LONG_INT) || (defined(MPI_VERSION) && MPI_VERSION >= 2)) +BOOST_MPI_DATATYPE(__int64, MPI_LONG_LONG_INT, builtin); #endif + +// Define unsigned long long or unsigned __int64 specialization of +// is_mpi_datatype, if possible. We separate this from the check for +// the (signed) long long/__int64 because some MPI implementations +// (e.g., MPICH-MX) have MPI_LONG_LONG_INT but not +// MPI_UNSIGNED_LONG_LONG. +#if defined(BOOST_HAS_LONG_LONG) && \ + (defined(MPI_UNSIGNED_LONG_LONG) \ + || (defined(MPI_VERSION) && MPI_VERSION >= 2)) +BOOST_MPI_DATATYPE(unsigned long long, MPI_UNSIGNED_LONG_LONG, builtin); +#elif defined(BOOST_HAS_MS_INT64) && \ + (defined(MPI_UNSIGNED_LONG_LONG) \ + || (defined(MPI_VERSION) && MPI_VERSION >= 2)) +BOOST_MPI_DATATYPE(unsigned __int64, MPI_UNSIGNED_LONG_LONG, builtin); #endif #endif // Doxygen diff --git a/include/boost/mpi/detail/mpi_datatype_cache.hpp b/include/boost/mpi/detail/mpi_datatype_cache.hpp index 2b3e1eb..766b460 100644 --- a/include/boost/mpi/detail/mpi_datatype_cache.hpp +++ b/include/boost/mpi/detail/mpi_datatype_cache.hpp @@ -15,7 +15,6 @@ #include #include #include -#include #include // The std::type_info::before function in Visual C++ 8.0 (and probably earlier) @@ -47,21 +46,15 @@ struct type_info_compare /// /// class BOOST_MPI_DECL mpi_datatype_map - : private std::map, - public boost::noncopyable + : public boost::noncopyable { -public: - mpi_datatype_map() - {} + struct implementation; - ~mpi_datatype_map() - { - // do not free after call to MPI_FInalize - int finalized=0; - BOOST_MPI_CHECK_RESULT(MPI_Finalized,(&finalized)); - if (!finalized) - free(); - } + implementation *impl; + +public: + mpi_datatype_map(); + ~mpi_datatype_map(); template MPI_Datatype datatype(const T& x = T(), typename boost::enable_if >::type* =0) @@ -76,30 +69,24 @@ public: // check whether the type already exists std::type_info const* t = &typeid(T); - const_iterator it = find(t); - if(it ==end()) - { + MPI_Datatype datatype = get(t); + if (datatype == MPI_DATATYPE_NULL) { // need to create a type mpi_datatype_oarchive ar(x); - insert(std::make_pair(t,ar.get_mpi_datatype())); - it = find(t); + datatype = ar.get_mpi_datatype(); + set(t, datatype); } - return it->second; + return datatype; } private: - // free all MPI data types - void free() - { - // ignore errors in the destructor - for (iterator it=begin(); it !=end(); ++it) - MPI_Type_free(&(it->second)); - } - + MPI_Datatype get(const std::type_info* t); + void set(const std::type_info* t, MPI_Datatype datatype); }; -extern mpi_datatype_map mpi_datatype_cache; +/// Retrieve the MPI datatype cache +mpi_datatype_map& mpi_datatype_cache(); } } } // end namespace boost::mpi::detail diff --git a/src/mpi_datatype_cache.cpp b/src/mpi_datatype_cache.cpp index 748171c..51ec98c 100644 --- a/src/mpi_datatype_cache.cpp +++ b/src/mpi_datatype_cache.cpp @@ -8,9 +8,54 @@ #include #include +#include namespace boost { namespace mpi { namespace detail { -mpi_datatype_map mpi_datatype_cache; - + typedef std::map + stored_map_type; + + struct mpi_datatype_map::implementation + { + stored_map_type map; + }; + + mpi_datatype_map::mpi_datatype_map() + { + impl = new implementation(); + } + + mpi_datatype_map::~mpi_datatype_map() + { + // do not free after call to MPI_FInalize + int finalized=0; + BOOST_MPI_CHECK_RESULT(MPI_Finalized,(&finalized)); + if (!finalized) { + // ignore errors in the destructor + for (stored_map_type::iterator it=impl->map.begin(); it != impl->map.end(); ++it) { + MPI_Type_free(&(it->second)); + } + } + delete impl; + } + + MPI_Datatype mpi_datatype_map::get(const std::type_info* t) + { + stored_map_type::iterator pos = impl->map.find(t); + if (pos != impl->map.end()) + return pos->second; + else + return MPI_DATATYPE_NULL; + } + + void mpi_datatype_map::set(const std::type_info* t, MPI_Datatype datatype) + { + impl->map[t] = datatype; + } + + mpi_datatype_map& mpi_datatype_cache() + { + static mpi_datatype_map cache; + return cache; + } } } }