diff --git a/src/include/darma/impl/access_handle/access_handle_serialization.h b/src/include/darma/impl/access_handle/access_handle_serialization.h index a1ba9c90..cfad2df0 100644 --- a/src/include/darma/impl/access_handle/access_handle_serialization.h +++ b/src/include/darma/impl/access_handle/access_handle_serialization.h @@ -252,7 +252,7 @@ AccessHandle::unpack_from_archive(Archive& ar) { var_handle_base_ = detail::make_shared>(k); - auto use_base = abstract::frontend::PolymorphicSerializableObject + auto use_base = serialization::PolymorphicSerializableObject ::unpack(*reinterpret_cast(&ar.data_pointer_reference())); use_base->set_handle(var_handle_base_); diff --git a/src/include/darma/impl/array/index_range.h b/src/include/darma/impl/array/index_range.h index ec4f56d6..069c601d 100644 --- a/src/include/darma/impl/array/index_range.h +++ b/src/include/darma/impl/array/index_range.h @@ -45,8 +45,9 @@ #ifndef DARMA_IMPL_ARRAY_INDEX_RANGE_H #define DARMA_IMPL_ARRAY_INDEX_RANGE_H +#include + #include -#include namespace darma_runtime { @@ -116,7 +117,7 @@ operator+ (IntegerConvertible&& other, ContiguousIndex const& idx) { template class ContiguousIndexRange - : public detail::PolymorphicSerializationAdapter< + : public serialization::PolymorphicSerializationAdapter< ContiguousIndexRange, abstract::frontend::IndexRange > diff --git a/src/include/darma/impl/collective/reduce_op.h b/src/include/darma/impl/collective/reduce_op.h index f83c24ca..1b7bf01a 100644 --- a/src/include/darma/impl/collective/reduce_op.h +++ b/src/include/darma/impl/collective/reduce_op.h @@ -46,19 +46,19 @@ #ifndef DARMA_IMPL_COLLECTIVE_REDUCE_OP_H #define DARMA_IMPL_COLLECTIVE_REDUCE_OP_H -#include -#include -#include -#include - #include #include #include #include -#include #include +#include + +#include +#include +#include +#include namespace darma_runtime { @@ -67,7 +67,7 @@ namespace detail { template class ReduceOperationWrapper - : public darma_runtime::detail::PolymorphicSerializationAdapter< + : public serialization::PolymorphicSerializationAdapter< ReduceOperationWrapper, abstract::frontend::ReduceOp >, diff --git a/src/include/darma/impl/handle_use_base.h b/src/include/darma/impl/handle_use_base.h index 26fec160..d8267c8d 100644 --- a/src/include/darma/impl/handle_use_base.h +++ b/src/include/darma/impl/handle_use_base.h @@ -68,7 +68,7 @@ class HandleUseBase public abstract::frontend::CollectionManagingUse, public abstract::frontend::UsePendingRegistration, public abstract::frontend::UsePendingRelease, - public abstract::frontend::PolymorphicSerializableObject + public serialization::PolymorphicSerializableObject { public: diff --git a/src/include/darma/impl/index_range/dense_range.h b/src/include/darma/impl/index_range/dense_range.h index 927a48e7..3adbd055 100644 --- a/src/include/darma/impl/index_range/dense_range.h +++ b/src/include/darma/impl/index_range/dense_range.h @@ -46,7 +46,7 @@ #define DARMA_IMPL_INDEX_RANGE_DENSE_RANGE_H #include -#include +#include namespace darma_runtime { namespace indexing { @@ -56,7 +56,7 @@ namespace detail { template class basic_dense_index_range : public abstract::frontend::IndexRange, - public darma_runtime::detail::PolymorphicSerializationAdapter< + public serialization::PolymorphicSerializationAdapter< basic_dense_index_range, abstract::frontend::IndexRange > diff --git a/src/include/darma/impl/index_range/range_1d.h b/src/include/darma/impl/index_range/range_1d.h index a7799078..0e10c098 100644 --- a/src/include/darma/impl/index_range/range_1d.h +++ b/src/include/darma/impl/index_range/range_1d.h @@ -52,7 +52,7 @@ #include -#include +#include #include namespace darma_runtime { @@ -129,7 +129,7 @@ template < typename... Properties > struct basic_integer_range_1d - : darma_runtime::detail::PolymorphicSerializationAdapter< + : serialization::PolymorphicSerializationAdapter< basic_integer_range_1d, abstract::frontend::IndexRange > diff --git a/src/include/darma/impl/index_range/range_2d.h b/src/include/darma/impl/index_range/range_2d.h index 9d3e55a9..9a6734e9 100644 --- a/src/include/darma/impl/index_range/range_2d.h +++ b/src/include/darma/impl/index_range/range_2d.h @@ -48,7 +48,8 @@ #include #include -#include +#include +#include namespace darma_runtime { @@ -77,7 +78,7 @@ struct Range2DDenseMapping; template struct Range2D - : detail::PolymorphicSerializationAdapter< + : serialization::PolymorphicSerializationAdapter< Range2D, abstract::frontend::IndexRange > diff --git a/src/include/darma/impl/polymorphic_serialization.h b/src/include/darma/impl/polymorphic_serialization.h deleted file mode 100644 index 6bfb7c0f..00000000 --- a/src/include/darma/impl/polymorphic_serialization.h +++ /dev/null @@ -1,540 +0,0 @@ -/* -//@HEADER -// ************************************************************************ -// -// polymorphic_serialization.h -// DARMA -// Copyright (C) 2017 NTESS, LLC -// -// Under the terms of Contract DE-NA-0003525 with NTESS, LLC, -// the U.S. Government retains certain rights in this software. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// 1. Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// -// 3. Neither the name of the Corporation nor the names of the -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY -// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE -// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// Questions? Contact darma@sandia.gov -// -// ************************************************************************ -//@HEADER -*/ - -#ifndef DARMA_IMPL_POLYMORPHIC_SERIALIZATION_H -#define DARMA_IMPL_POLYMORPHIC_SERIALIZATION_H - -#include // function -#include // unique_ptr -#include -#include - -#include - -#include -#include -#include -#include - -#include - -//#ifndef DARMA_INITIAL_ABSTRACT_BASE_REGISTRY_SIZE -//#define DARMA_INITIAL_ABSTRACT_BASE_REGISTRY_SIZE 32 -//#endif - - -namespace darma_runtime { -namespace detail { - -// TODO this could be sped up a bit in specific cases where certain AbstractBase disallow multiple inheritance for derived types - -template -using abstract_base_unpack_registry = - std::vector< - std::function(char const*& buffer)> - >; - -template -size_t& -get_known_abstract_base_count() { - static size_t abstract_base_count = 0; - return abstract_base_count; -} - -template -abstract_base_unpack_registry& -get_polymorphic_unpack_registry() { - static abstract_base_unpack_registry _reg; - return _reg; -} - -struct SerializedPolymorphicObjectHeader { - size_t n_bases : 8; - // Pad to 128 bits for now to make alignment work out reasonably in the most - // common case, where there's only one base - size_t _unused1 : 56; - size_t _unused2 : 64; -}; - -struct PolymorphicAbstractBasesTableEntry { - size_t abstract_index : 64; - size_t concrete_index : 64; -}; - -namespace _impl { - -//============================================================================== -// {{{1 - -template -struct PolymorphicUnpackRegistrar; - -//------------------------------------------------------------------------------ -// {{{2 - -// Use longer names in the adapters to avoid collisions with user-defined functions named "unpack" -template -using _has_static_long_name_unpack_as_archetype = decltype( - T::template _darma_static_polymorphic_serializable_adapter_unpack_as(std::declval()) -); - -template -using _has_static_long_name_unpack_as = meta::is_detected_convertible< - std::unique_ptr, _has_static_long_name_unpack_as_archetype, T, AbstractBase ->; - -template -using _has_static_long_name_unpack_archetype = decltype( - T::_darma_static_polymorphic_serializable_adapter_unpack(std::declval()) -); - -template -using _has_static_long_name_unpack = meta::is_detected_convertible< - std::unique_ptr, _has_static_long_name_unpack_archetype, T ->; - -template -using _has_static_unpack_as_archetype = decltype( T::template unpack_as(std::declval()) ); - -template -using _has_static_unpack_as = meta::is_detected_convertible< - std::unique_ptr, _has_static_unpack_as_archetype, T, AbstractBase ->; - -template -using _has_static_unpack_archetype = decltype( T::unpack(std::declval()) ); - -template -using _has_static_unpack = meta::is_detected_convertible< - std::unique_ptr, _has_static_unpack_archetype, T ->; - -enum struct _static_unpack_hook_option { - long_name_unpack_as, - long_name_unpack, - unpack_as, - unpack -}; - -template <_static_unpack_hook_option val> -using _wrapped_hook = std::integral_constant<_static_unpack_hook_option, val>; - -template <_static_unpack_hook_option option, typename T, typename AbstractBase> -using _enable_if_static_unpack_hook_case = std::enable_if_t< - tinympl::select_first< - _has_static_long_name_unpack_as, - /* => */ _wrapped_hook<_static_unpack_hook_option::long_name_unpack_as>, - _has_static_long_name_unpack, - /* => */ _wrapped_hook<_static_unpack_hook_option::long_name_unpack>, - _has_static_unpack_as, - /* => */ _wrapped_hook<_static_unpack_hook_option::unpack_as>, - _has_static_unpack, - /* => */ _wrapped_hook<_static_unpack_hook_option::unpack> - >::type::value == option ->; - -// end static unpack detection }}}2 -//------------------------------------------------------------------------------ - -template -struct PolymorphicUnpackRegistrar ->{ - size_t index; - PolymorphicUnpackRegistrar() { - auto& reg = get_polymorphic_unpack_registry(); - index = reg.size(); - reg.emplace_back([](char const*& buffer) { - return ConcreteType::template unpack_as(buffer); - }); - } -}; - -template -struct PolymorphicUnpackRegistrar ->{ - size_t index; - PolymorphicUnpackRegistrar() { - auto& reg = get_polymorphic_unpack_registry(); - index = reg.size(); - reg.emplace_back([](char const*& buffer) { - return ConcreteType::unpack(buffer); - }); - } -}; - -template -struct PolymorphicUnpackRegistrar ->{ - size_t index; - PolymorphicUnpackRegistrar() { - auto& reg = get_polymorphic_unpack_registry(); - index = reg.size(); - reg.emplace_back([](char const*& buffer) { - return ConcreteType::template _darma_static_polymorphic_serializable_adapter_unpack_as(buffer); - }); - } -}; - -template -struct PolymorphicUnpackRegistrar ->{ - size_t index; - PolymorphicUnpackRegistrar() { - auto& reg = get_polymorphic_unpack_registry(); - index = reg.size(); - reg.emplace_back([](char const*& buffer) { - return ConcreteType::_darma_static_polymorphic_serializable_adapter_unpack(buffer); - }); - } -}; - -template -struct PolymorphicUnpackRegistrarWrapper { - static PolymorphicUnpackRegistrar registrar; -}; - -template -PolymorphicUnpackRegistrar -PolymorphicUnpackRegistrarWrapper::registrar = { }; - -// end PolymorphicUnpackRegistrar }}}1 -//============================================================================== - - -template -struct AbstractBaseRegistrar { - size_t index; - AbstractBaseRegistrar() { - auto& count = get_known_abstract_base_count(); - index = count; - ++count; - } -}; - -template -struct AbstractBaseRegistrarWrapper { - static AbstractBaseRegistrar registrar; -}; - -template -AbstractBaseRegistrar - AbstractBaseRegistrarWrapper::registrar = { }; - -} // end namespace _impl - -template -size_t -get_abstract_type_index() { - return _impl::AbstractBaseRegistrarWrapper::registrar.index; -} - -template -struct polymorphic_serialization_details { - template - struct with_abstract_bases { - static void - add_registry_frontmatter_in_place(char* buffer) { - // add the header - new (buffer) SerializedPolymorphicObjectHeader{ - /* n_bases = */ static_cast(sizeof...(AbstractBases)), - /* unused */ 0ull, - /* also unused */ 0ull - }; - // advance the buffer - buffer += sizeof(SerializedPolymorphicObjectHeader); - - // add the array of abstract-to-concrete index pairs - new (buffer) PolymorphicAbstractBasesTableEntry[sizeof...(AbstractBases)] { - PolymorphicAbstractBasesTableEntry{ - get_abstract_type_index(), - _impl::PolymorphicUnpackRegistrarWrapper< - AbstractBases, - ConcreteType - >::registrar.index - }... - }; - } - static constexpr auto registry_frontmatter_size = - sizeof(SerializedPolymorphicObjectHeader) - + sizeof(PolymorphicAbstractBasesTableEntry[sizeof...(AbstractBases)]); - using concrete_t = ConcreteType; - }; -}; - -template -struct _polymorphic_serialization_adapter_impl : BaseT { - - private: - using polymorphic_details_t = Details; - using concrete_t = typename Details::concrete_t; - using serialization_handler_t = SerializationHandler; - - protected: - // Perfect forwarding ctor - template - _polymorphic_serialization_adapter_impl( - Args&&... args - ) : BaseT(std::forward(args)...) - { } - - public: - - size_t get_packed_size() const override { - auto ar = serialization_handler_t::make_sizing_archive(); - // call the customization point, allow ADL - darma_compute_size(*static_cast(this), ar); - return serialization_handler_t::get_size(ar) + polymorphic_details_t::registry_frontmatter_size; - } - - void pack(char*& buffer) const override { - polymorphic_details_t::add_registry_frontmatter_in_place(buffer); - buffer += polymorphic_details_t::registry_frontmatter_size; - auto ar = serialization_handler_t::make_packing_archive( - buffer - ); - // call the customization point, allow ADL - darma_pack(*static_cast(this), ar); - } - -}; - -//============================================================================== -// {{{1 - -// Adapter for single abstract base -template > - > -> -struct PolymorphicSerializationAdapter - : _polymorphic_serialization_adapter_impl< - typename polymorphic_serialization_details::template with_abstract_bases, - BaseT, - SerializationHandler - > -{ - private: - using serialization_handler_t = SerializationHandler; - using impl_t = _polymorphic_serialization_adapter_impl< - typename polymorphic_serialization_details::template with_abstract_bases, - BaseT, - serialization_handler_t - >; - - protected: - - template - PolymorphicSerializationAdapter( - Args&&... args - ) : impl_t(std::forward(args)...) - { } - - public: - - static - std::unique_ptr - _darma_static_polymorphic_serializable_adapter_unpack(char const*& buffer) { - - // TODO ask the abstract object for an allocator? - // There's no way to use make_unique here; we just have to allocate and then - // construct the unique_ptr from the pointer we allocate - void* allocated_spot = darma_runtime::abstract::backend::get_backend_memory_manager() - ->allocate(sizeof(ConcreteT)); - - auto ar = serialization_handler_t::make_unpacking_archive(buffer); - - // call the customization point, allow ADL - darma_unpack( - darma_runtime::serialization::allocated_buffer_for(allocated_spot), ar - ); - - std::unique_ptr rv(reinterpret_cast(allocated_spot)); - - return std::move(rv); - } -}; - -// Adapter for multiple abstract bases -template -struct PolymorphicSerializationAdapter, BaseT, - darma_runtime::serialization::PointerReferenceSerializationHandler< - darma_runtime::serialization::SimpleSerializationHandler> - > -> : _polymorphic_serialization_adapter_impl< - typename polymorphic_serialization_details::template with_abstract_bases, - BaseT, - darma_runtime::serialization::PointerReferenceSerializationHandler< - darma_runtime::serialization::SimpleSerializationHandler> - > - > -{ - private: - using serialization_handler_t = darma_runtime::serialization::PointerReferenceSerializationHandler< - darma_runtime::serialization::SimpleSerializationHandler> - >; - using impl_t = _polymorphic_serialization_adapter_impl< - typename polymorphic_serialization_details::template with_abstract_bases< - AbstractTypes... - >, - BaseT, serialization_handler_t - >; - - protected: - - template - PolymorphicSerializationAdapter( - Args&&... args - ) : impl_t(std::forward(args)...) - { } - - public: - - template < - typename AbstractT, - typename=std::enable_if_t< - tinympl::variadic::find::value != sizeof...(AbstractTypes) - > - > - static - std::unique_ptr - _darma_static_polymorphic_serializable_adapter_unpack_as(char const*& buffer) { - - // TODO ask the abstract object for an allocator? - // There's no way to use make_unique here; we just have to allocate and then - // construct the unique_ptr from the pointer we allocate - void* allocated_spot = darma_runtime::abstract::backend::get_backend_memory_manager() - ->allocate(sizeof(ConcreteT)); - - auto ar = serialization_handler_t::make_unpacking_archive(buffer); - - darma_unpack( - darma_runtime::serialization::allocated_buffer_for(allocated_spot), ar - ); - - std::unique_ptr rv(reinterpret_cast(allocated_spot)); - - return std::move(rv); - } -}; - -// end PolymorphicSerializationAdapter }}}1 -//============================================================================== - -} // end namespace detail - -namespace abstract { -namespace frontend { - -template -std::unique_ptr -PolymorphicSerializableObject::unpack(char const*& buffer) { - // Get the abstract type index that we're looking for - static const size_t abstract_type_index = - darma_runtime::detail::get_abstract_type_index(); - - // Get the header - auto const& header = *reinterpret_cast< - darma_runtime::detail::SerializedPolymorphicObjectHeader const* - >(buffer); - buffer += sizeof(darma_runtime::detail::SerializedPolymorphicObjectHeader); - - // Look through the abstract bases that this object is registered for until - // we find the entry that corresponds to a callable that unpacks the object - // as a std::unique_ptr - uint8_t i_base = 0; - size_t concrete_index = std::numeric_limits::max(); - for(; i_base < header.n_bases; ++i_base) { - const auto& entry = *reinterpret_cast< - darma_runtime::detail::PolymorphicAbstractBasesTableEntry const* - >(buffer); - - if (abstract_type_index == entry.abstract_index) { - // We found the one we want to call, so break - concrete_index = entry.concrete_index; - break; - } - - buffer += sizeof(darma_runtime::detail::PolymorphicAbstractBasesTableEntry); - } - DARMA_ASSERT_MESSAGE( - concrete_index != std::numeric_limits::max(), - "No registered unpacker found to unpack a concrete type as abstract type " - << darma_runtime::utility::try_demangle::name() - ); - - // Make sure we advance the buffer over all of the other base class entries - buffer += sizeof(darma_runtime::detail::PolymorphicAbstractBasesTableEntry) * (header.n_bases - i_base); - - // get a reference to the static registry - auto& reg = darma_runtime::detail::get_polymorphic_unpack_registry(); - - // execute the unpack callable on the buffer - return reg[concrete_index](buffer); -} - -} // end namespace frontend -} // end namespace abstract - -} // end namespace darma_runtime - - -#endif //DARMA_IMPL_POLYMORPHIC_SERIALIZATION_H diff --git a/src/include/darma/impl/task/functor_task.h b/src/include/darma/impl/task/functor_task.h index 545af5bc..bc49cd3a 100644 --- a/src/include/darma/impl/task/functor_task.h +++ b/src/include/darma/impl/task/functor_task.h @@ -51,13 +51,13 @@ #include #include #include -#include - -#include #include "task_base.h" #include "task_ctor_helper.h" +#include +#include + #include namespace darma_runtime { @@ -151,7 +151,7 @@ template < > struct FunctorTask #if _darma_has_feature(task_migration) - : PolymorphicSerializationAdapter< + : serialization::PolymorphicSerializationAdapter< FunctorTask, abstract::frontend::Task, TaskBase @@ -164,7 +164,7 @@ struct FunctorTask public: #if _darma_has_feature(task_migration) - using base_t = PolymorphicSerializationAdapter< + using base_t = serialization::PolymorphicSerializationAdapter< FunctorTask, abstract::frontend::Task, TaskBase diff --git a/src/include/darma/impl/task/lambda_task.h b/src/include/darma/impl/task/lambda_task.h index 0af56065..94638838 100644 --- a/src/include/darma/impl/task/lambda_task.h +++ b/src/include/darma/impl/task/lambda_task.h @@ -45,7 +45,7 @@ #ifndef DARMAFRONTEND_LAMBDA_TASK_H #define DARMAFRONTEND_LAMBDA_TASK_H -#include +#include #include "task_base.h" #include "task_ctor_helper.h" @@ -245,7 +245,7 @@ constexpr struct no_double_copy_capture_tag_t {} no_double_copy_capture_tag = { template struct LambdaTask #if _darma_has_feature(task_migration) - : PolymorphicSerializationAdapter< + : serialization::PolymorphicSerializationAdapter< LambdaTask, abstract::frontend::Task, TaskBase @@ -264,7 +264,7 @@ struct LambdaTask using capturer_t = LambdaCapturer; #if _darma_has_feature(task_migration) - using base_t = PolymorphicSerializationAdapter< + using base_t = serialization::PolymorphicSerializationAdapter< LambdaTask, abstract::frontend::Task, TaskBase diff --git a/src/include/darma/impl/task/task.h b/src/include/darma/impl/task/task.h index 5b45d14d..a0de2faf 100644 --- a/src/include/darma/impl/task/task.h +++ b/src/include/darma/impl/task/task.h @@ -100,7 +100,7 @@ namespace frontend { inline abstract::backend::runtime_t::task_unique_ptr unpack_task(void const* packed_data) { - return darma_runtime::abstract::frontend::PolymorphicSerializableObject< + return serialization::PolymorphicSerializableObject< abstract::frontend::Task >::unpack(*reinterpret_cast(&packed_data)); } diff --git a/src/include/darma/impl/task/task_base.h b/src/include/darma/impl/task/task_base.h index a3c12430..5a91ce2c 100644 --- a/src/include/darma/impl/task/task_base.h +++ b/src/include/darma/impl/task/task_base.h @@ -75,6 +75,7 @@ #include #include +#include #include // for task calling file and function #include @@ -92,7 +93,6 @@ #include #include #include -#include #include namespace darma_runtime { @@ -575,7 +575,7 @@ class EmptyTask : public TaskBase { class NonMigratableTaskBase - : public PolymorphicSerializationAdapter< + : public serialization::PolymorphicSerializationAdapter< NonMigratableTaskBase, TaskBase > diff --git a/src/include/darma/impl/task_collection/access_handle_collection.h b/src/include/darma/impl/task_collection/access_handle_collection.h index e9ea8435..7c98653a 100644 --- a/src/include/darma/impl/task_collection/access_handle_collection.h +++ b/src/include/darma/impl/task_collection/access_handle_collection.h @@ -518,7 +518,7 @@ class AccessHandleCollection ::darma_runtime::detail::VariableHandle >(key); - auto use_base = abstract::frontend::PolymorphicSerializableObject + auto use_base = serialization::PolymorphicSerializableObject ::unpack(*reinterpret_cast(&ar.data_pointer_reference())); this->set_current_use( diff --git a/src/include/darma/impl/task_collection/task_collection.h b/src/include/darma/impl/task_collection/task_collection.h index e4fbccae..d6c2d4a0 100644 --- a/src/include/darma/impl/task_collection/task_collection.h +++ b/src/include/darma/impl/task_collection/task_collection.h @@ -48,7 +48,7 @@ #include #if _darma_has_feature(create_concurrent_work) -#include +#include #include #include #include @@ -77,7 +77,7 @@ template < > struct TaskCollectionImpl #if _darma_has_feature(task_migration) - : PolymorphicSerializationAdapter< + : serialization::PolymorphicSerializationAdapter< TaskCollectionImpl, abstract::frontend::TaskCollection > diff --git a/src/include/darma/impl/task_collection/task_collection_task.h b/src/include/darma/impl/task_collection/task_collection_task.h index 5bb1b328..f52bd7b1 100644 --- a/src/include/darma/impl/task_collection/task_collection_task.h +++ b/src/include/darma/impl/task_collection/task_collection_task.h @@ -193,12 +193,15 @@ template < typename... StoredArgs > struct TaskCollectionTaskImpl - : PolymorphicSerializationAdapter< + : serialization::PolymorphicSerializationAdapter< TaskCollectionTaskImpl, abstract::frontend::TaskCollectionTask > { - using base_t = abstract::frontend::TaskCollectionTask; + using base_t = serialization::PolymorphicSerializationAdapter< + TaskCollectionTaskImpl, + abstract::frontend::TaskCollectionTask + >; using args_tuple_t = std::tuple; diff --git a/src/include/darma/impl/top_level.h b/src/include/darma/impl/top_level.h index 9842f4b6..0c3f0788 100644 --- a/src/include/darma/impl/top_level.h +++ b/src/include/darma/impl/top_level.h @@ -46,16 +46,17 @@ #define DARMA_IMPL_TOP_LEVEL_H -#include #include +#include -#include +#include #include +#include #include // for arguments #include // for arguments -#include +#include namespace darma_runtime { @@ -105,7 +106,7 @@ struct TopLevelCallableRegistrar { struct TopLevelTaskImpl #if _darma_has_feature(task_migration) - : PolymorphicSerializationAdapter< + : serialization::PolymorphicSerializationAdapter< TopLevelTaskImpl, abstract::frontend::Task, abstract::frontend::TopLevelTask diff --git a/src/include/darma/impl/use.h b/src/include/darma/impl/use.h index a40f6464..01cb87ae 100644 --- a/src/include/darma/impl/use.h +++ b/src/include/darma/impl/use.h @@ -59,14 +59,14 @@ #include #include #include -#include "polymorphic_serialization.h" +#include namespace darma_runtime { namespace detail { class HandleUse - : public PolymorphicSerializationAdapter + : public serialization::PolymorphicSerializationAdapter { private: diff --git a/src/include/darma/impl/use_collection.h b/src/include/darma/impl/use_collection.h index e485ea4b..f9831ca7 100644 --- a/src/include/darma/impl/use_collection.h +++ b/src/include/darma/impl/use_collection.h @@ -45,7 +45,6 @@ #ifndef DARMA_IMPL_USE_COLLECTION_H #define DARMA_IMPL_USE_COLLECTION_H -#include // abstract::frontend::UseCollection #include #include @@ -53,6 +52,10 @@ #include // flow_ptr #include // HandleUseBase +#include // abstract::frontend::UseCollection + +#include + namespace darma_runtime { namespace detail { @@ -63,7 +66,7 @@ static constexpr struct cloning_ctor_tag_t { } cloning_ctor_tag { }; template class BasicUseCollection : public abstract::frontend::UseCollection, - public abstract::frontend::PolymorphicSerializableObject> + public serialization::PolymorphicSerializableObject> { public: // All public for now, rather than dealing with making friend declarations for AccessHandleCollection and friends @@ -156,14 +159,14 @@ class BasicUseCollection template class UnmappedUseCollection final /* final for now, at least */ - : public PolymorphicSerializationAdapter< + : public serialization::PolymorphicSerializationAdapter< UnmappedUseCollection, BasicUseCollection > { public: - using base_t = PolymorphicSerializationAdapter< + using base_t = serialization::PolymorphicSerializationAdapter< UnmappedUseCollection, BasicUseCollection >; @@ -248,7 +251,7 @@ make_unmapped_use_collection(Args&&... args) { template class MappedUseCollection final /* final for now, at least */ - : public PolymorphicSerializationAdapter< + : public serialization::PolymorphicSerializationAdapter< MappedUseCollection, BasicUseCollection > @@ -267,7 +270,7 @@ class MappedUseCollection final /* final for now, at least */ mapping_t mapping_fe_handle_to_be_task_; using mapping_traits_t = darma_runtime::indexing::mapping_traits; - using base_t = PolymorphicSerializationAdapter< + using base_t = serialization::PolymorphicSerializationAdapter< MappedUseCollection, BasicUseCollection >; @@ -433,14 +436,14 @@ make_mapped_use_collection(UnmappedCollectionT&& clone_from, Args&&... args) { template class BasicCollectionManagingUse final /* final for now, at least */ - : public PolymorphicSerializationAdapter< + : public serialization::PolymorphicSerializationAdapter< BasicCollectionManagingUse, HandleUseBase > { public: - using base_t = PolymorphicSerializationAdapter< + using base_t = serialization::PolymorphicSerializationAdapter< BasicCollectionManagingUse, HandleUseBase >; @@ -590,7 +593,7 @@ class BasicCollectionManagingUse final /* final for now, at least */ static void unpack(void* allocated, Archive& ar) { auto* rv = new (allocated) BasicCollectionManagingUse(); auto ptr_ar = serialization::PointerReferenceSerializationHandler<>::make_unpacking_archive_referencing(ar); - rv->collection_ = abstract::frontend::PolymorphicSerializableObject> + rv->collection_ = serialization::PolymorphicSerializableObject> ::unpack(*reinterpret_cast(&ar.data_pointer_reference())); rv->HandleUseBase::do_serialize(ar); } diff --git a/src/include/darma/interface/frontend/index_range.h b/src/include/darma/interface/frontend/index_range.h index be512963..99626787 100644 --- a/src/include/darma/interface/frontend/index_range.h +++ b/src/include/darma/interface/frontend/index_range.h @@ -45,9 +45,9 @@ #ifndef DARMA_INTERFACE_FRONTEND_INDEX_RANGE_H #define DARMA_INTERFACE_FRONTEND_INDEX_RANGE_H -#include // size_t +#include -#include "polymorphic_serializable_object.h" +#include // size_t namespace darma_runtime { namespace abstract { @@ -57,7 +57,7 @@ namespace frontend { * */ class IndexRange - : public PolymorphicSerializableObject + : public serialization::PolymorphicSerializableObject { public: /** diff --git a/src/include/darma/interface/frontend/reduce_operation.h b/src/include/darma/interface/frontend/reduce_operation.h index 54fee907..798bf1fe 100644 --- a/src/include/darma/interface/frontend/reduce_operation.h +++ b/src/include/darma/interface/frontend/reduce_operation.h @@ -47,7 +47,8 @@ #include -#include +#include + #include #include @@ -55,7 +56,7 @@ namespace darma_runtime { namespace abstract { namespace frontend { -class ReduceOp : public PolymorphicSerializableObject { +class ReduceOp : public serialization::PolymorphicSerializableObject { public: virtual ~ReduceOp(){} diff --git a/src/include/darma/interface/frontend/task.h b/src/include/darma/interface/frontend/task.h index 6f330322..ba5f404f 100644 --- a/src/include/darma/interface/frontend/task.h +++ b/src/include/darma/interface/frontend/task.h @@ -45,7 +45,6 @@ #ifndef SRC_ABSTRACT_FRONTEND_TASK_H_ #define SRC_ABSTRACT_FRONTEND_TASK_H_ -#include #include #include @@ -56,6 +55,10 @@ #include "use.h" +#include + +#include + namespace darma_runtime { namespace abstract { @@ -124,7 +127,7 @@ class Closure { */ class Task #if _darma_has_feature(task_migration) - : public PolymorphicSerializableObject, + : public serialization::PolymorphicSerializableObject, #endif public Closure { diff --git a/src/include/darma/interface/frontend/task_collection.h b/src/include/darma/interface/frontend/task_collection.h index 3c24e28c..5f272105 100644 --- a/src/include/darma/interface/frontend/task_collection.h +++ b/src/include/darma/interface/frontend/task_collection.h @@ -47,7 +47,7 @@ #include // types::handle_container_template<> -#include +#include #include @@ -66,7 +66,7 @@ namespace frontend { */ class TaskCollection #if _darma_has_feature(task_migration) - : public PolymorphicSerializableObject + : public serialization::PolymorphicSerializableObject #endif //_darma_has_feature(task_migration) { public: diff --git a/src/include/darma/serialization/polymorphic/CMakeLists.txt b/src/include/darma/serialization/polymorphic/CMakeLists.txt new file mode 100644 index 00000000..cf2d0f59 --- /dev/null +++ b/src/include/darma/serialization/polymorphic/CMakeLists.txt @@ -0,0 +1,12 @@ + +set(DARMA_SERIALIZATION_POLYMORPHIC_HEADERS + impl/polymorphic_serializable_object.impl.h + polymorphic_serializable_object.h + polymorphic_serialization_adapter.h + registry.h +) + +install (FILES ${DARMA_SERIALIZATION_POLYMORPHIC_HEADERS} + DESTINATION include/darma/serialization/serializers +) + diff --git a/src/include/darma/serialization/polymorphic/impl/polymorphic_serializable_object.impl.h b/src/include/darma/serialization/polymorphic/impl/polymorphic_serializable_object.impl.h new file mode 100644 index 00000000..67f12bf8 --- /dev/null +++ b/src/include/darma/serialization/polymorphic/impl/polymorphic_serializable_object.impl.h @@ -0,0 +1,109 @@ +/* +//@HEADER +// ************************************************************************ +// +// polymorphic_serialization.h +// DARMA +// Copyright (C) 2017 NTESS, LLC +// +// Under the terms of Contract DE-NA-0003525 with NTESS, LLC, +// the U.S. Government retains certain rights in this software. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// 3. Neither the name of the Corporation nor the names of the +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Questions? Contact darma@sandia.gov +// +// ************************************************************************ +//@HEADER +*/ + +#ifndef DARMA_IMPL_POLYMORPHIC_SERIALIZATION_H +#define DARMA_IMPL_POLYMORPHIC_SERIALIZATION_H + +#include +#include + +#include +#include + +#include // unique_ptr + +namespace darma_runtime { +namespace serialization { + +template +std::unique_ptr +PolymorphicSerializableObject::unpack(char const*& buffer) { + // Get the abstract type index that we're looking for + static const size_t abstract_type_index = + darma_runtime::serialization::detail::get_abstract_type_index(); + + // Get the header + auto const& header = *reinterpret_cast< + darma_runtime::serialization::detail::SerializedPolymorphicObjectHeader const* + >(buffer); + buffer += sizeof(darma_runtime::serialization::detail::SerializedPolymorphicObjectHeader); + + // Look through the abstract bases that this object is registered for until + // we find the entry that corresponds to a callable that unpacks the object + // as a std::unique_ptr + uint8_t i_base = 0; + size_t concrete_index = std::numeric_limits::max(); + for(; i_base < header.n_bases; ++i_base) { + const auto& entry = *reinterpret_cast< + darma_runtime::serialization::detail::PolymorphicAbstractBasesTableEntry const* + >(buffer); + + if (abstract_type_index == entry.abstract_index) { + // We found the one we want to call, so break + concrete_index = entry.concrete_index; + break; + } + + buffer += sizeof(darma_runtime::serialization::detail::PolymorphicAbstractBasesTableEntry); + } + DARMA_ASSERT_MESSAGE( + concrete_index != std::numeric_limits::max(), + "No registered unpacker found to unpack a concrete type as abstract type " + << darma_runtime::utility::try_demangle::name() + ); + + // Make sure we advance the buffer over all of the other base class entries + buffer += sizeof(darma_runtime::serialization::detail::PolymorphicAbstractBasesTableEntry) * (header.n_bases - i_base); + + // get a reference to the static registry + auto& reg = darma_runtime::serialization::detail::get_polymorphic_unpack_registry(); + + // execute the unpack callable on the buffer + return reg[concrete_index](buffer); +} + +} // end namespace serialization +} // end namespace darma_runtime + +#endif //DARMA_IMPL_POLYMORPHIC_SERIALIZATION_H diff --git a/src/include/darma/interface/frontend/polymorphic_serializable_object.h b/src/include/darma/serialization/polymorphic/polymorphic_serializable_object.h similarity index 94% rename from src/include/darma/interface/frontend/polymorphic_serializable_object.h rename to src/include/darma/serialization/polymorphic/polymorphic_serializable_object.h index 3bb344f8..0a24a8bc 100644 --- a/src/include/darma/interface/frontend/polymorphic_serializable_object.h +++ b/src/include/darma/serialization/polymorphic/polymorphic_serializable_object.h @@ -48,8 +48,7 @@ #include // std::unique_ptr namespace darma_runtime { -namespace abstract { -namespace frontend { +namespace serialization { template struct PolymorphicSerializableObject { @@ -64,8 +63,9 @@ struct PolymorphicSerializableObject { }; -} // end namespace frontend -} // end namespace abstract +} // end namespace serialization } // end namespace darma_runtime +#include + #endif //DARMA_ABSTRACT_FRONTEND_POLYMORPHIC_SERIALIZABLE_OBJECT_H diff --git a/src/include/darma/serialization/polymorphic/polymorphic_serialization_adapter.h b/src/include/darma/serialization/polymorphic/polymorphic_serialization_adapter.h new file mode 100644 index 00000000..bc617434 --- /dev/null +++ b/src/include/darma/serialization/polymorphic/polymorphic_serialization_adapter.h @@ -0,0 +1,258 @@ +/* +//@HEADER +// ************************************************************************ +// +// polymorphic_serialization_adapter.h +// DARMA +// Copyright (C) 2018 Sandia Corporation +// +// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation, +// the U.S. Government retains certain rights in this software. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// 3. Neither the name of the Corporation nor the names of the +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Questions? Contact David S. Hollman (dshollm@sandia.gov) +// +// ************************************************************************ +//@HEADER +*/ + +#ifndef DARMAFRONTEND_POLYMORPHIC_SERIALIZATION_ADAPTER_H +#define DARMAFRONTEND_POLYMORPHIC_SERIALIZATION_ADAPTER_H + +#include +#include + +#include + +namespace darma_runtime { +namespace serialization { + + +//============================================================================== +// {{{1 + +namespace detail { + +template +struct polymorphic_serialization_details { + template + struct with_abstract_bases { + static void + add_registry_frontmatter_in_place(char* buffer) { + // add the header + new (buffer) SerializedPolymorphicObjectHeader{ + /* n_bases = */ static_cast(sizeof...(AbstractBases)), + /* unused */ 0ull, + /* also unused */ 0ull + }; + // advance the buffer + buffer += sizeof(SerializedPolymorphicObjectHeader); + + // add the array of abstract-to-concrete index pairs + new (buffer) PolymorphicAbstractBasesTableEntry[sizeof...(AbstractBases)] { + PolymorphicAbstractBasesTableEntry{ + get_abstract_type_index(), + _impl::PolymorphicUnpackRegistrarWrapper< + AbstractBases, + ConcreteType + >::registrar.index + }... + }; + } + static constexpr auto registry_frontmatter_size = + sizeof(SerializedPolymorphicObjectHeader) + + sizeof(PolymorphicAbstractBasesTableEntry[sizeof...(AbstractBases)]); + using concrete_t = ConcreteType; + }; +}; + +template +struct _polymorphic_serialization_adapter_impl : BaseT { + + private: + using polymorphic_details_t = Details; + using concrete_t = typename Details::concrete_t; + using serialization_handler_t = SerializationHandler; + + protected: + // Perfect forwarding ctor + template + _polymorphic_serialization_adapter_impl( + Args&&... args + ) : BaseT(std::forward(args)...) + { } + + public: + + size_t get_packed_size() const override { + auto ar = serialization_handler_t::make_sizing_archive(); + // call the customization point, allow ADL + darma_compute_size(*static_cast(this), ar); + return serialization_handler_t::get_size(ar) + polymorphic_details_t::registry_frontmatter_size; + } + + void pack(char*& buffer) const override { + polymorphic_details_t::add_registry_frontmatter_in_place(buffer); + buffer += polymorphic_details_t::registry_frontmatter_size; + auto ar = serialization_handler_t::make_packing_archive( + buffer + ); + // call the customization point, allow ADL + darma_pack(*static_cast(this), ar); + } + +}; + +} // end namespace detail + +// Adapter for single abstract base +template > + > +> +struct PolymorphicSerializationAdapter + : detail::_polymorphic_serialization_adapter_impl< + typename detail::polymorphic_serialization_details::template with_abstract_bases, + BaseT, + SerializationHandler + > +{ + private: + using serialization_handler_t = SerializationHandler; + using impl_t = detail::_polymorphic_serialization_adapter_impl< + typename detail::polymorphic_serialization_details::template with_abstract_bases, + BaseT, + serialization_handler_t + >; + + protected: + + template + PolymorphicSerializationAdapter( + Args&&... args + ) : impl_t(std::forward(args)...) + { } + + public: + + static + std::unique_ptr + _darma_static_polymorphic_serializable_adapter_unpack(char const*& buffer) { + + // TODO ask the abstract object for an allocator? Or allocate some other way? + using allocator_t = std::allocator; + using allocator_traits_t = std::allocator_traits; + allocator_t alloc; + void* allocated_spot = std::allocator_traits::allocate(alloc, 1); + + auto ar = serialization_handler_t::make_unpacking_archive(buffer); + + // call the customization point, allow ADL + darma_unpack( + darma_runtime::serialization::allocated_buffer_for(allocated_spot), ar + ); + + std::unique_ptr rv(reinterpret_cast(allocated_spot)); + + return std::move(rv); + } +}; + +// Adapter for multiple abstract bases +template +struct PolymorphicSerializationAdapter, BaseT, + darma_runtime::serialization::PointerReferenceSerializationHandler< + darma_runtime::serialization::SimpleSerializationHandler> + > +> : detail::_polymorphic_serialization_adapter_impl< + typename detail::polymorphic_serialization_details::template with_abstract_bases, + BaseT, + darma_runtime::serialization::PointerReferenceSerializationHandler< + darma_runtime::serialization::SimpleSerializationHandler> + > + > +{ + private: + using serialization_handler_t = darma_runtime::serialization::PointerReferenceSerializationHandler< + darma_runtime::serialization::SimpleSerializationHandler> + >; + using impl_t = detail::_polymorphic_serialization_adapter_impl< + typename detail::polymorphic_serialization_details::template with_abstract_bases< + AbstractTypes... + >, + BaseT, serialization_handler_t + >; + + protected: + + template + PolymorphicSerializationAdapter( + Args&&... args + ) : impl_t(std::forward(args)...) + { } + + public: + + template < + typename AbstractT, + typename=std::enable_if_t< + tinympl::variadic::find::value != sizeof...(AbstractTypes) + > + > + static + std::unique_ptr + _darma_static_polymorphic_serializable_adapter_unpack_as(char const*& buffer) { + + // TODO ask the abstract object for an allocator? Or allocate some other way? + using allocator_t = std::allocator; + using allocator_traits_t = std::allocator_traits; + allocator_t alloc; + void* allocated_spot = std::allocator_traits::allocate(alloc, 1); + + auto ar = serialization_handler_t::make_unpacking_archive(buffer); + + darma_unpack( + darma_runtime::serialization::allocated_buffer_for(allocated_spot), ar + ); + + std::unique_ptr rv(reinterpret_cast(allocated_spot)); + + return std::move(rv); + } +}; + +// end PolymorphicSerializationAdapter }}}1 +//============================================================================== + +} // end namespace serialization +} // end namespace darma_runtime + +#endif //DARMAFRONTEND_POLYMORPHIC_SERIALIZATION_ADAPTER_H diff --git a/src/include/darma/serialization/polymorphic/registry.h b/src/include/darma/serialization/polymorphic/registry.h new file mode 100644 index 00000000..02a3f0e9 --- /dev/null +++ b/src/include/darma/serialization/polymorphic/registry.h @@ -0,0 +1,283 @@ +/* +//@HEADER +// ************************************************************************ +// +// registry.h +// DARMA +// Copyright (C) 2018 Sandia Corporation +// +// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation, +// the U.S. Government retains certain rights in this software. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// 3. Neither the name of the Corporation nor the names of the +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Questions? Contact David S. Hollman (dshollm@sandia.gov) +// +// ************************************************************************ +//@HEADER +*/ + +#ifndef DARMAFRONTEND_SERIALIZATION_POLYMORPHIC_REGISTRY_H +#define DARMAFRONTEND_SERIALIZATION_POLYMORPHIC_REGISTRY_H + +#include +#include + +#include // function +#include +#include +#include + +namespace darma_runtime { +namespace serialization { +namespace detail { + +// TODO this could be sped up a bit in specific cases where certain AbstractBase disallow multiple inheritance for derived types + +template +using abstract_base_unpack_registry = + std::vector< + std::function(char const*& buffer)> + >; + +template +size_t& +get_known_abstract_base_count() { + static size_t abstract_base_count = 0; + return abstract_base_count; +} + +template +abstract_base_unpack_registry& +get_polymorphic_unpack_registry() { + static abstract_base_unpack_registry _reg; + return _reg; +} + +struct SerializedPolymorphicObjectHeader { + size_t n_bases : 8; + // Pad to 128 bits for now to make alignment work out reasonably in the most + // common case, where there's only one base + size_t _unused1 : 56; + size_t _unused2 : 64; +}; + +struct PolymorphicAbstractBasesTableEntry { + size_t abstract_index : 64; + size_t concrete_index : 64; +}; + +namespace _impl { + +//============================================================================== +// {{{1 + +template +struct PolymorphicUnpackRegistrar; + +//------------------------------------------------------------------------------ +// {{{2 + +// Use longer names in the adapters to avoid collisions with user-defined functions named "unpack" +template +using _has_static_long_name_unpack_as_archetype = decltype( + T::template _darma_static_polymorphic_serializable_adapter_unpack_as(std::declval()) +); + +template +using _has_static_long_name_unpack_as = tinympl::is_detected_convertible< + std::unique_ptr, _has_static_long_name_unpack_as_archetype, T, AbstractBase +>; + +template +using _has_static_long_name_unpack_archetype = decltype( + T::_darma_static_polymorphic_serializable_adapter_unpack(std::declval()) +); + +template +using _has_static_long_name_unpack = tinympl::is_detected_convertible< + std::unique_ptr, _has_static_long_name_unpack_archetype, T +>; + +template +using _has_static_unpack_as_archetype = decltype( T::template unpack_as(std::declval()) ); + +template +using _has_static_unpack_as = tinympl::is_detected_convertible< + std::unique_ptr, _has_static_unpack_as_archetype, T, AbstractBase +>; + +template +using _has_static_unpack_archetype = decltype( T::unpack(std::declval()) ); + +template +using _has_static_unpack = tinympl::is_detected_convertible< + std::unique_ptr, _has_static_unpack_archetype, T +>; + +enum struct _static_unpack_hook_option { + long_name_unpack_as, + long_name_unpack, + unpack_as, + unpack +}; + +template <_static_unpack_hook_option val> +using _wrapped_hook = std::integral_constant<_static_unpack_hook_option, val>; + +template <_static_unpack_hook_option option, typename T, typename AbstractBase> +using _enable_if_static_unpack_hook_case = std::enable_if_t< + tinympl::select_first< + _has_static_long_name_unpack_as, + /* => */ _wrapped_hook<_static_unpack_hook_option::long_name_unpack_as>, + _has_static_long_name_unpack, + /* => */ _wrapped_hook<_static_unpack_hook_option::long_name_unpack>, + _has_static_unpack_as, + /* => */ _wrapped_hook<_static_unpack_hook_option::unpack_as>, + _has_static_unpack, + /* => */ _wrapped_hook<_static_unpack_hook_option::unpack> + >::type::value == option +>; + +// end static unpack detection }}}2 +//------------------------------------------------------------------------------ + +template +struct PolymorphicUnpackRegistrar +>{ + size_t index; + PolymorphicUnpackRegistrar() { + auto& reg = get_polymorphic_unpack_registry(); + index = reg.size(); + reg.emplace_back([](char const*& buffer) { + return ConcreteType::template unpack_as(buffer); + }); + } +}; + +template +struct PolymorphicUnpackRegistrar +>{ + size_t index; + PolymorphicUnpackRegistrar() { + auto& reg = get_polymorphic_unpack_registry(); + index = reg.size(); + reg.emplace_back([](char const*& buffer) { + return ConcreteType::unpack(buffer); + }); + } +}; + +template +struct PolymorphicUnpackRegistrar +>{ + size_t index; + PolymorphicUnpackRegistrar() { + auto& reg = get_polymorphic_unpack_registry(); + index = reg.size(); + reg.emplace_back([](char const*& buffer) { + return ConcreteType::template _darma_static_polymorphic_serializable_adapter_unpack_as(buffer); + }); + } +}; + +template +struct PolymorphicUnpackRegistrar +>{ + size_t index; + PolymorphicUnpackRegistrar() { + auto& reg = get_polymorphic_unpack_registry(); + index = reg.size(); + reg.emplace_back([](char const*& buffer) { + return ConcreteType::_darma_static_polymorphic_serializable_adapter_unpack(buffer); + }); + } +}; + +template +struct PolymorphicUnpackRegistrarWrapper { + static PolymorphicUnpackRegistrar registrar; +}; + +template +PolymorphicUnpackRegistrar +PolymorphicUnpackRegistrarWrapper::registrar = { }; + +// end PolymorphicUnpackRegistrar }}}1 +//============================================================================== + + +template +struct AbstractBaseRegistrar { + size_t index; + AbstractBaseRegistrar() { + auto& count = get_known_abstract_base_count(); + index = count; + ++count; + } +}; + +template +struct AbstractBaseRegistrarWrapper { + static AbstractBaseRegistrar registrar; +}; + +template +AbstractBaseRegistrar + AbstractBaseRegistrarWrapper::registrar = { }; + +} // end namespace _impl + +template +size_t +get_abstract_type_index() { + return _impl::AbstractBaseRegistrarWrapper::registrar.index; +} + + +} // end namespace detail +} // end namespace serialization +} // end namespace darma_runtime + +#endif //DARMAFRONTEND_SERIALIZATION_POLYMORPHIC_REGISTRY_H diff --git a/src/tests/frontend_validation/test_functor_migrate.cc b/src/tests/frontend_validation/test_functor_migrate.cc index 63599d41..1a9a9a2b 100644 --- a/src/tests/frontend_validation/test_functor_migrate.cc +++ b/src/tests/frontend_validation/test_functor_migrate.cc @@ -246,7 +246,7 @@ TEST_F_WITH_PARAMS( })); char const* unpack_spot = buffer; - auto migrated_task = darma_runtime::abstract::frontend + auto migrated_task = darma_runtime::serialization ::PolymorphicSerializableObject ::unpack(unpack_spot); diff --git a/src/tests/frontend_validation/test_task_collection.cc b/src/tests/frontend_validation/test_task_collection.cc index c3d4bea3..fd023b71 100644 --- a/src/tests/frontend_validation/test_task_collection.cc +++ b/src/tests/frontend_validation/test_task_collection.cc @@ -666,7 +666,7 @@ TEST_F(TestCreateConcurrentWork, migrate_simple) { char const* unpack_buffer_spot = buffer; - auto copied_collection = abstract::frontend::PolymorphicSerializableObject< + auto copied_collection = serialization::PolymorphicSerializableObject< abstract::frontend::TaskCollection >::unpack(unpack_buffer_spot);