diff --git a/include/continuable/continuable-traverse-async.hpp b/include/continuable/continuable-traverse-async.hpp new file mode 100644 index 0000000..d219172 --- /dev/null +++ b/include/continuable/continuable-traverse-async.hpp @@ -0,0 +1,119 @@ + +/* + + /~` _ _ _|_. _ _ |_ | _ + \_,(_)| | | || ||_|(_||_)|(/_ + + https://github.com/Naios/continuable + v2.0.0 + + Copyright(c) 2015 - 2018 Denis Blank + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files(the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and / or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions : + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +**/ + +#ifndef CONTINUABLE_TRAVERSE_ASYNC_HPP_INCLUDED +#define CONTINUABLE_TRAVERSE_ASYNC_HPP_INCLUDED + +#include + +#include + +namespace cti { +/// A tag which is passed to the `operator()` of the visitor +/// if an element is visited synchronously. +using detail::async_traverse_visit_tag; +/// A tag which is passed to the `operator()` of the visitor +/// if an element is visited after the traversal was detached. +using detail::async_traverse_detach_tag; +/// A tag which is passed to the `operator()` of the visitor +/// if the asynchronous pack traversal was finished. +using detail::async_traverse_complete_tag; + +/// A tag to identify that a mapper shall be constructed in-place +/// from the first argument passed. +using detail::async_traverse_in_place_tag; + +/// Traverses the pack with the given visitor in an asynchronous way. +/// +/// This function works in the same way as `traverse_pack`, +/// however, we are able to suspend and continue the traversal at +/// later time. +/// Thus we require a visitor callable object which provides three +/// `operator()` overloads as depicted by the code sample below: +/// ```cpp +/// struct my_async_visitor +/// { +/// /// The synchronous overload is called for each object, +/// /// it may return false to suspend the current control. +/// /// In that case the overload below is called. +/// template +/// bool operator()(async_traverse_visit_tag, T&& element) +/// { +/// return true; +/// } +/// +/// /// The asynchronous overload this is called when the +/// /// synchronous overload returned false. +/// /// In addition to the current visited element the overload is +/// /// called with a contnuation callable object which resumes the +/// /// traversal when it's called later. +/// /// The continuation next may be stored and called later or +/// /// dropped completely to abort the traversal early. +/// template +/// void operator()(async_traverse_detach_tag, T&& element, N&& next) +/// { +/// } +/// +/// /// The overload is called when the traversal was finished. +/// /// As argument the whole pack is passed over which we +/// /// traversed asynchrnously. +/// template +/// void operator()(async_traverse_complete_tag, T&& pack) +/// { +/// } +/// }; +/// ``` +/// +/// \param visitor A visitor object which provides the three `operator()` +/// overloads that were described above. +/// Additionally the visitor must be compatible +/// for referencing it from a `boost::intrusive_ptr`. +/// The visitor should must have a virtual destructor! +/// +/// \param pack The arbitrary parameter pack which is traversed +/// asynchronously. Nested objects inside containers and +/// tuple like types are traversed recursively. +/// +/// \returns A boost::intrusive_ptr that references an instance of +/// the given visitor object. +/// +/// See `traverse_pack` for a detailed description about the +/// traversal behaviour and capabilities. +/// +template +auto traverse_pack_async(Visitor&& visitor, T&&... pack) + -> decltype(detail::apply_pack_transform_async( + std::forward(visitor), std::forward(pack)...)) { + return detail::apply_pack_transform_async(std::forward(visitor), + std::forward(pack)...); +} +} // namespace cti + +#endif // CONTINUABLE_TRAVERSE_ASYNC_HPP_INCLUDED diff --git a/include/continuable/continuable-traverse.hpp b/include/continuable/continuable-traverse.hpp new file mode 100644 index 0000000..fa37f34 --- /dev/null +++ b/include/continuable/continuable-traverse.hpp @@ -0,0 +1,106 @@ + +/* + + /~` _ _ _|_. _ _ |_ | _ + \_,(_)| | | || ||_|(_||_)|(/_ + + https://github.com/Naios/continuable + v2.0.0 + + Copyright(c) 2015 - 2018 Denis Blank + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files(the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and / or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions : + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +**/ + +#ifndef CONTINUABLE_TRAVERSE_HPP_INCLUDED +#define CONTINUABLE_TRAVERSE_HPP_INCLUDED + +#include +#include +#include + +#include + +namespace cti { +/// Maps the pack with the given mapper. +/// +/// This function tries to visit all plain elements which may be wrapped in: +/// - homogeneous containers (`std::vector`, `std::list`) +/// - heterogenous containers `(hpx::tuple`, `std::pair`, `std::array`) +/// and re-assembles the pack with the result of the mapper. +/// Mapping from one type to a different one is supported. +/// +/// Elements that aren't accepted by the mapper are routed through +/// and preserved through the hierarchy. +/// +/// ```cpp +/// // Maps all integers to floats +/// map_pack([](int value) { +/// return float(value); +/// }, +/// 1, hpx::util::make_tuple(2, std::vector{3, 4}), 5); +/// ``` +/// +/// \throws std::exception like objects which are thrown by an +/// invocation to the mapper. +/// +/// \param mapper A callable object, which accept an arbitrary type +/// and maps it to another type or the same one. +/// +/// \param pack An arbitrary variadic pack which may contain any type. +/// +/// \returns The mapped element or in case the pack contains +/// multiple elements, the pack is wrapped into +/// a `hpx::tuple`. +/// +template +auto map_pack(Mapper&& mapper, T&&... pack) + -> decltype(detail::apply_pack_transform(detail::strategy_remap_tag{}, + std::forward(mapper), + std::forward(pack)...)) { + return detail::apply_pack_transform(detail::strategy_remap_tag{}, + std::forward(mapper), + std::forward(pack)...); +} + +/// Indicate that the result shall be spread across the parent container +/// if possible. This can be used to create a mapper function used +/// in map_pack that maps one element to an arbitrary count (1:n). +template +constexpr detail::spreading::spread_box::type...> +spread_this(T&&... args) { + return detail::spreading::spread_box::type...>( + util::make_tuple(std::forward(args)...)); +} + +/// Traverses the pack with the given visitor. +/// +/// This function works in the same way as `map_pack`, +/// however, the result of the mapper isn't preserved. +/// +/// See `map_pack` for a detailed description. +template +void traverse_pack(Mapper&& mapper, T&&... pack) { + detail::apply_pack_transform(detail::strategy_traverse_tag{}, + std::forward(mapper), + std::forward(pack)...); +} +} // namespace cti + +#endif // CONTINUABLE_TRAVERSE_HPP_INCLUDED diff --git a/include/continuable/detail/pack-traversal-async.hpp b/include/continuable/detail/traverse-async.hpp similarity index 99% rename from include/continuable/detail/pack-traversal-async.hpp rename to include/continuable/detail/traverse-async.hpp index a322ec6..8cc062c 100644 --- a/include/continuable/detail/pack-traversal-async.hpp +++ b/include/continuable/detail/traverse-async.hpp @@ -28,8 +28,8 @@ SOFTWARE. **/ -#ifndef CONTINUABLE_DETAIL_PACK_TRAVERSAL_ASYNC_HPP_INCLUDED -#define CONTINUABLE_DETAIL_PACK_TRAVERSAL_ASYNC_HPP_INCLUDED +#ifndef CONTINUABLE_DETAIL_TRAVERSE_ASYNC_HPP_INCLUDED +#define CONTINUABLE_DETAIL_TRAVERSE_ASYNC_HPP_INCLUDED #include #include @@ -558,4 +558,4 @@ auto apply_pack_transform_async(Visitor&& visitor, Args&&... args) -> } // namespace detail } // namespace cti -#endif // CONTINUABLE_DETAIL_PACK_TRAVERSAL_ASYNC_HPP_INCLUDED +#endif // CONTINUABLE_DETAIL_TRAVERSE_ASYNC_HPP_INCLUDED diff --git a/include/continuable/detail/pack-traversal.hpp b/include/continuable/detail/traverse.hpp similarity index 99% rename from include/continuable/detail/pack-traversal.hpp rename to include/continuable/detail/traverse.hpp index 02bbf59..9272e83 100644 --- a/include/continuable/detail/pack-traversal.hpp +++ b/include/continuable/detail/traverse.hpp @@ -28,8 +28,8 @@ SOFTWARE. **/ -#ifndef CONTINUABLE_DETAIL_PACK_TRAVERSAL_HPP_INCLUDED -#define CONTINUABLE_DETAIL_PACK_TRAVERSAL_HPP_INCLUDED +#ifndef CONTINUABLE_DETAIL_TRAVERSE_HPP_INCLUDED +#define CONTINUABLE_DETAIL_TRAVERSE_HPP_INCLUDED #include #include @@ -842,4 +842,4 @@ auto apply_pack_transform(Strategy strategy, Mapper&& mapper, T&&... pack) } // namespace detail } // namespace cti -#endif // CONTINUABLE_DETAIL_PACK_TRAVERSAL_HPP_INCLUDED +#endif // CONTINUABLE_DETAIL_TRAVERSE_HPP_INCLUDED diff --git a/test/playground/CMakeLists.txt b/test/playground/CMakeLists.txt index b88d819..f39d4e4 100644 --- a/test/playground/CMakeLists.txt +++ b/test/playground/CMakeLists.txt @@ -5,6 +5,8 @@ set(LIB_SOURCES ${CMAKE_SOURCE_DIR}/include/continuable/continuable-trait.hpp ${CMAKE_SOURCE_DIR}/include/continuable/continuable-promise-base.hpp ${CMAKE_SOURCE_DIR}/include/continuable/continuable-transforms.hpp + ${CMAKE_SOURCE_DIR}/include/continuable/continuable-traverse.hpp + ${CMAKE_SOURCE_DIR}/include/continuable/continuable-traverse-async.hpp ${CMAKE_SOURCE_DIR}/include/continuable/continuable-testing.hpp) set(LIB_SOURCES_DETAIL ${CMAKE_SOURCE_DIR}/include/continuable/detail/awaiting.hpp @@ -13,8 +15,8 @@ set(LIB_SOURCES_DETAIL ${CMAKE_SOURCE_DIR}/include/continuable/detail/expected.hpp ${CMAKE_SOURCE_DIR}/include/continuable/detail/hints.hpp ${CMAKE_SOURCE_DIR}/include/continuable/detail/container-category.hpp - ${CMAKE_SOURCE_DIR}/include/continuable/detail/pack-traversal.hpp - ${CMAKE_SOURCE_DIR}/include/continuable/detail/pack-traversal-async.hpp + ${CMAKE_SOURCE_DIR}/include/continuable/detail/traverse.hpp + ${CMAKE_SOURCE_DIR}/include/continuable/detail/traverse-async.hpp ${CMAKE_SOURCE_DIR}/include/continuable/detail/features.hpp ${CMAKE_SOURCE_DIR}/include/continuable/detail/traits.hpp ${CMAKE_SOURCE_DIR}/include/continuable/detail/transforms.hpp