Skip to content

Commit

Permalink
Merge pull request #2116 from STEllAR-GROUP/bind-simple
Browse files Browse the repository at this point in the history
Use a lightweight bind implementation when no placeholders are given
  • Loading branch information
hkaiser committed Apr 30, 2016
2 parents c970723 + 7114deb commit 38dcdab
Show file tree
Hide file tree
Showing 18 changed files with 217 additions and 1,766 deletions.
7 changes: 6 additions & 1 deletion hpx/traits/is_bind_expression.hpp
Expand Up @@ -24,6 +24,11 @@ namespace hpx { namespace traits
: boost::false_type
#endif
{};

template <typename T>
struct is_bind_expression<T const>
: is_bind_expression<T>
{};
}}

#endif
#endif /*HPX_TRAITS_IS_BIND_EXPRESSION_HPP*/
7 changes: 6 additions & 1 deletion hpx/traits/is_placeholder.hpp
Expand Up @@ -30,6 +30,11 @@ namespace hpx { namespace traits
: boost::is_placeholder<T>
#endif
{};

template <typename T>
struct is_placeholder<T const>
: is_placeholder<T>
{};
}}

#endif
#endif /*HPX_TRAITS_IS_PLACEHOLDER_HPP*/
171 changes: 95 additions & 76 deletions hpx/util/bind.hpp
@@ -1,5 +1,5 @@
// Copyright (c) 2011-2012 Thomas Heller
// Copyright (c) 2013-2015 Agustin Berge
// Copyright (c) 2013-2016 Agustin Berge
//
// Distributed under 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)
Expand All @@ -21,9 +21,7 @@
#include <hpx/util/detail/pack.hpp>

#include <boost/type_traits/integral_constant.hpp>
#include <boost/ref.hpp>

#include <functional>
#include <type_traits>
#include <utility>

Expand Down Expand Up @@ -84,27 +82,27 @@ namespace hpx { namespace util
static HPX_FORCEINLINE
type call(T& t, Us&& /*unbound*/)
{
return std::move(t);
return std::forward<T>(t);
}
};

template <
typename F, typename T, typename TD, typename Us,
typename F, typename T, typename Us,
typename Enable = void
>
struct bind_eval_impl
: bind_eval_bound_impl<F, T>
{};

template <
std::size_t I, typename T, typename Us,
std::size_t I, typename Us,
typename Enable = void
>
struct bind_eval_placeholder_impl
{};

template <std::size_t I, typename T, typename Us>
struct bind_eval_placeholder_impl<I, T, Us,
template <std::size_t I, typename Us>
struct bind_eval_placeholder_impl<I, Us,
typename std::enable_if<
(I < util::tuple_size<Us>::value)
>::type
Expand All @@ -114,28 +112,28 @@ namespace hpx { namespace util
I, typename util::decay<Us>::type
>::type&& type;

template <typename T>
static HPX_FORCEINLINE
type call(T /*t*/, Us&& unbound)
type call(T&& /*t*/, Us&& unbound)
{
return util::get<I>(std::forward<Us>(unbound));
}
};

template <typename F, typename T, typename TD, typename Us>
struct bind_eval_impl<F, T, TD, Us,
template <typename F, typename T, typename Us>
struct bind_eval_impl<F, T, Us,
typename std::enable_if<
traits::is_placeholder<TD>::value != 0
traits::is_placeholder<T>::value != 0
>::type
> : bind_eval_placeholder_impl<
static_cast<std::size_t>(traits::is_placeholder<TD>::value - 1),
T, Us
(std::size_t)traits::is_placeholder<T>::value - 1, Us
>
{};

template <typename F, typename T, typename TD, typename Us>
struct bind_eval_impl<F, T, TD, Us,
template <typename F, typename T, typename Us>
struct bind_eval_impl<F, T, Us,
typename std::enable_if<
traits::is_bind_expression<TD>::value
traits::is_bind_expression<T>::value
>::type
>
{
Expand All @@ -146,90 +144,111 @@ namespace hpx { namespace util
static HPX_FORCEINLINE
type call(T& t, Us&& unbound)
{
return util::invoke_fused(
t, std::forward<Us>(unbound));
}
};

template <typename F, typename T, typename X, typename Us>
struct bind_eval_impl<F, T, ::boost::reference_wrapper<X>, Us>
{
typedef X& type;

static HPX_FORCEINLINE
type call(T& t, Us&& /*unbound*/)
{
return t.get();
return util::invoke_fused(t, std::forward<Us>(unbound));
}
};

#if defined(HPX_HAVE_CXX11_STD_REFERENCE_WRAPPER)
template <typename F, typename T, typename X, typename Us>
struct bind_eval_impl<F, T, ::std::reference_wrapper<X>, Us>
{
typedef X& type;

static HPX_FORCEINLINE
type call(T& t, Us&& /*unbound*/)
{
return t.get();
}
};
#endif

template <typename F, typename T, typename Us>
HPX_FORCEINLINE
typename bind_eval_impl<F, T, typename std::decay<T>::type, Us>::type
typename bind_eval_impl<F, T, Us>::type
bind_eval(T& t, Us&& unbound)
{
return bind_eval_impl<F, T, typename std::decay<T>::type, Us>::call(
t, std::forward<Us>(unbound));
return bind_eval_impl<F, T, Us>::call(
t, std::forward<Us>(unbound));
}

///////////////////////////////////////////////////////////////////////
template <typename Ts>
struct is_simple_bind;

template <typename ...Ts>
struct is_simple_bind<util::tuple<Ts...> >
: detail::none_of<
traits::is_placeholder<Ts>...,
traits::is_bind_expression<Ts>...
>
{};

template <typename ...Ts>
struct is_simple_bind<util::tuple<Ts...> const>
: is_simple_bind<util::tuple<Ts const...> >
{};

///////////////////////////////////////////////////////////////////////
template <typename F, typename Ts, typename Us>
struct bound_result_of;
struct bound_result_of_impl;

template <typename F, typename ...Ts, typename Us>
struct bound_result_of<
F, util::tuple<Ts...>, Us
> : util::result_of<
F(typename bind_eval_impl<
F, Ts, typename std::decay<Ts>::type, Us
>::type&&...)
struct bound_result_of_impl<F, util::tuple<Ts...>, Us>
: util::result_of<
F&(typename bind_eval_impl<F, Ts, Us>::type&&...)
>
{};

template <typename F, typename ...Ts, typename Us>
struct bound_result_of<
F, util::tuple<Ts...> const, Us
> : util::result_of<
F(typename bind_eval_impl<
F, Ts const, typename std::decay<Ts>::type, Us
>::type&&...)
>
template <typename F, typename Ts>
struct bound_result_of_simple_impl;

template <typename F, typename ...Ts>
struct bound_result_of_simple_impl<F, util::tuple<Ts...> >
: util::result_of<F&(Ts&...)>
{};

template <typename F, typename ...Ts>
struct bound_result_of_simple_impl<one_shot_wrapper<F>, util::tuple<Ts...> >
: util::result_of<F&&(Ts&&...)>
{};

///////////////////////////////////////////////////////////////////////
template <typename F, typename Ts, typename Us>
struct bound_result_of
: std::conditional<
!detail::is_simple_bind<Ts>::value,
bound_result_of_impl<F, Ts, Us>,
bound_result_of_simple_impl<F, Ts>
>::type
{};

template <typename F, typename ...Ts, typename Us>
struct bound_result_of<
one_shot_wrapper<F> const, util::tuple<Ts...>, Us
>
struct bound_result_of<F, util::tuple<Ts...> const, Us>
: bound_result_of<F, util::tuple<Ts const...>, Us>
{};

template <typename F, typename ...Ts, typename Us>
struct bound_result_of<
one_shot_wrapper<F> const, util::tuple<Ts...> const, Us
>
{};
one_shot_wrapper<F> const, util::tuple<Ts...> const, Us>
{}; // one-shot wrapper is not const callable

///////////////////////////////////////////////////////////////////////
template <typename F, typename Ts, typename Us, std::size_t ...Is>
typename bound_result_of<F, Ts, Us>::type
bound_impl(F& f, Ts& bound, Us&& unbound,
typename std::enable_if<
!detail::is_simple_bind<Ts>::value,
typename bound_result_of<F, Ts, Us>::type
>::type bound_impl(F& f, Ts& bound, Us&& unbound,
pack_c<std::size_t, Is...>)
{
return util::invoke(f,
detail::bind_eval<F, typename util::tuple_element<Is, Ts>::type>(
util::get<Is>(bound), std::forward<Us>(unbound))...);
}

template <typename F, typename Ts, typename Us, std::size_t ...Is>
typename std::enable_if<
detail::is_simple_bind<Ts>::value,
typename bound_result_of<F, Ts, Us>::type
>::type bound_impl(F& f, Ts& bound, Us&& /*unbound*/,
pack_c<std::size_t, Is...>)
{
return util::invoke(f, util::get<Is>(bound)...);
}

template <typename F, typename Ts, typename Us, std::size_t ...Is>
typename std::enable_if<
detail::is_simple_bind<Ts>::value,
typename bound_result_of<one_shot_wrapper<F>, Ts, Us>::type
>::type bound_impl(one_shot_wrapper<F>& f, Ts& bound, Us&& /*unbound*/,
pack_c<std::size_t, Is...>)
{
return util::invoke(f, detail::bind_eval<F>(
util::get<Is>(bound), std::forward<Us>(unbound))...);
return util::invoke(std::move(f), util::get<Is>(std::move(bound))...);
}

template <typename T>
Expand Down Expand Up @@ -267,7 +286,7 @@ namespace hpx { namespace util
template <typename ...Us>
inline typename bound_result_of<
typename std::decay<F>::type,
util::tuple<typename std::decay<Ts>::type...>,
util::tuple<typename util::decay_unwrap<Ts>::type...>,
util::tuple<Us&&...>
>::type operator()(Us&&... vs)
{
Expand All @@ -279,7 +298,7 @@ namespace hpx { namespace util
template <typename ...Us>
inline typename bound_result_of<
typename std::decay<F>::type const,
util::tuple<typename std::decay<Ts>::type const...>,
util::tuple<typename util::decay_unwrap<Ts>::type...> const,
util::tuple<Us&&...>
>::type operator()(Us&&... vs) const
{
Expand All @@ -304,7 +323,7 @@ namespace hpx { namespace util

private:
typename std::decay<F>::type _f;
util::tuple<typename std::decay<Ts>::type...> _args;
util::tuple<typename util::decay_unwrap<Ts>::type...> _args;
};
}

Expand Down

0 comments on commit 38dcdab

Please sign in to comment.