From c67c8f8882a47a45ebb974cc2afccbfb8d81a6ea Mon Sep 17 00:00:00 2001 From: Douglas Gregor Date: Thu, 10 Apr 2008 21:05:14 +0000 Subject: [PATCH] Refactor mpi_datatype_cache to fix problems on VC9 [SVN r44160] --- include/boost/mpi/datatype.hpp | 2 +- .../boost/mpi/detail/mpi_datatype_cache.hpp | 45 ++++++----------- src/mpi_datatype_cache.cpp | 49 ++++++++++++++++++- 3 files changed, 64 insertions(+), 32 deletions(-) diff --git a/include/boost/mpi/datatype.hpp b/include/boost/mpi/datatype.hpp index 3412724..70600df 100644 --- a/include/boost/mpi/datatype.hpp +++ b/include/boost/mpi/datatype.hpp @@ -182,7 +182,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. 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; + } } } }