text:
// Copyright (C) 2012-2013 Vicente J. Botet Escriba
//
//  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)

// 2013/04 Vicente J. Botet Escriba
//    Provide implementation up to 9 parameters when BOOST_NO_CXX11_VARIADIC_TEMPLATES is defined.
//    Make use of Boost.Move
//    Make use of Boost.Tuple (movable)
// 2012 Vicente J. Botet Escriba
//    Provide implementation _RET using bind when BOOST_NO_CXX11_HDR_FUNCTIONAL and BOOST_NO_SFINAE_EXPR are not defined
// 2012 Vicente J. Botet Escriba
//    Adapt to boost libc++ implementation

//===----------------------------------------------------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.TXT for details.
//
// The invoke code is based on the one from libcxx.
//===----------------------------------------------------------------------===//

#ifndef BOOST_THREAD_DETAIL_INVOKE_HPP
#define BOOST_THREAD_DETAIL_INVOKE_HPP

#include <boost/config.hpp>
#include <boost/static_assert.hpp>
#include <boost/thread/detail/move.hpp>
#include <boost/core/enable_if.hpp>
#include <boost/mpl/bool.hpp>
#include <boost/type_traits/is_base_of.hpp>
#include <boost/type_traits/is_pointer.hpp>
#include <boost/type_traits/is_member_function_pointer.hpp>
#include <boost/type_traits/remove_reference.hpp>
#ifndef BOOST_NO_CXX11_HDR_FUNCTIONAL
#include <functional>
#endif

namespace boost
{
  namespace detail
  {

#if ! defined(BOOST_NO_SFINAE_EXPR) && \
    ! defined(BOOST_NO_CXX11_DECLTYPE) && \
    ! defined(BOOST_NO_CXX11_DECLTYPE_N3276) && \
    ! defined(BOOST_THREAD_NO_CXX11_DECLTYPE_N3276) && \
    ! defined(BOOST_NO_CXX11_TRAILING_RESULT_TYPES)

#define BOOST_THREAD_PROVIDES_INVOKE

#if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
    // bullets 1 and 2

    template <class Fp, class A0, class ...Args>
    inline auto
    invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(Args) ...args)
        -> decltype((boost::forward<A0>(a0).*f)(boost::forward<Args>(args)...))
    {
        return (boost::forward<A0>(a0).*f)(boost::forward<Args>(args)...);
    }
    template <class R, class Fp, class A0, class ...Args>
    inline auto
    invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(Args) ...args)
        -> decltype((boost::forward<A0>(a0).*f)(boost::forward<Args>(args)...))
    {
        return (boost::forward<A0>(a0).*f)(boost::forward<Args>(args)...);
    }

    template <class Fp, class A0, class ...Args>
    inline auto
    invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(Args) ...args)
        -> decltype(((*boost::forward<A0>(a0)).*f)(boost::forward<Args>(args)...))
    {
        return ((*boost::forward<A0>(a0)).*f)(boost::forward<Args>(args)...);
    }
    template <class R, class Fp, class A0, class ...Args>
    inline auto
    invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(Args) ...args)
        -> decltype(((*boost::forward<A0>(a0)).*f)(boost::forward<Args>(args)...))
    {
        return ((*boost::forward<A0>(a0)).*f)(boost::forward<Args>(args)...);
    }

    // bullets 3 and 4

    template <class Fp, class A0>
    inline auto
    invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A0) a0)
        -> decltype(boost::forward<A0>(a0).*f)
    {
        return boost::forward<A0>(a0).*f;
    }

    template <class Fp, class A0>
    inline auto
    invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A0) a0)
        -> decltype((*boost::forward<A0>(a0)).*f)
    {
        return (*boost::forward<A0>(a0)).*f;
    }

    template <class R, class Fp, class A0>
    inline auto
    invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A0) a0)
        -> decltype(boost::forward<A0>(a0).*f)
    {
        return boost::forward<A0>(a0).*f;
    }

    template <class R, class Fp, class A0>
    inline auto
    invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A0) a0)
        -> decltype((*boost::forward<A0>(a0)).*f)
    {
        return (*boost::forward<A0>(a0)).*f;
    }

    // bullet 5

    template <class R, class Fp, class ...Args>
    inline auto invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(Args) ...args)
    -> decltype(boost::forward<Fp>(f)(boost::forward<Args>(args)...))
    {
      return boost::forward<Fp>(f)(boost::forward<Args>(args)...);
    }
    template <class Fp, class ...Args>
    inline auto invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(Args) ...args)
    -> decltype(boost::forward<Fp>(f)(boost::forward<Args>(args)...))
    {
      return boost::forward<Fp>(f)(boost::forward<Args>(args)...);
    }

#else // BOOST_NO_CXX11_VARIADIC_TEMPLATES

    // bullets 1 and 2

    template <class Fp, class A0>
    inline
    auto
    invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A0) a0)
        -> decltype((boost::forward<A0>(a0).*f)())
    {
        return (boost::forward<A0>(a0).*f)();
    }
    template <class R, class Fp, class A0>
    inline
    auto
    invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A0) a0)
        -> decltype((boost::forward<A0>(a0).*f)())
    {
        return (boost::forward<A0>(a0).*f)();
    }
    template <class Fp, class A0, class A1>
    inline
    auto
    invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(A1) a1)
        -> decltype((boost::forward<A0>(a0).*f)(boost::forward<A1>(a1)))
    {
        return (boost::forward<A0>(a0).*f)(boost::forward<A1>(a1));
    }
    template <class R, class Fp, class A0, class A1>
    inline
    auto
    invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(A1) a1)
        -> decltype((boost::forward<A0>(a0).*f)(boost::forward<A1>(a1)))
    {
        return (boost::forward<A0>(a0).*f)(boost::forward<A1>(a1));
    }
    template <class Fp, class A0, class A1, class A2>
    inline
    auto
    invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2)
        -> decltype((boost::forward<A0>(a0).*f)(boost::forward<A1>(a1), boost::forward<A2>(a2)))
    {
        return (boost::forward<A0>(a0).*f)(boost::forward<A1>(a1), boost::forward<A2>(a2));
    }
    template <class R, class Fp, class A0, class A1, class A2>
    inline
    auto
    invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2)
        -> decltype((boost::forward<A0>(a0).*f)(boost::forward<A1>(a1), boost::forward<A2>(a2)))
    {
        return (boost::forward<A0>(a0).*f)(boost::forward<A1>(a1), boost::forward<A2>(a2));
    }

    template <class Fp, class A0>
    inline
    auto
    invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A0) a0)
        -> decltype(((*boost::forward<A0>(a0)).*f)())
    {
        return ((*boost::forward<A0>(a0)).*f)();
    }
    template <class R, class Fp, class A0>
    inline
    auto
    invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A0) a0)
        -> decltype(((*boost::forward<A0>(a0)).*f)())
    {
        return ((*boost::forward<A0>(a0)).*f)();
    }
    template <class Fp, class A0, class A1>
    inline
    auto
    invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(A1) a1)
        -> decltype(((*boost::forward<A0>(a0)).*f)(boost::forward<A1>(a1)))
    {
        return ((*boost::forward<A0>(a0)).*f)(boost::forward<A1>(a1));
    }
    template <class R, class Fp, class A0, class A1>
    inline
    auto
    invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(A1) a1)
        -> decltype(((*boost::forward<A0>(a0)).*f)(boost::forward<A1>(a1)))
    {
        return ((*boost::forward<A0>(a0)).*f)(boost::forward<A1>(a1));
    }
    template <class Fp, class A0, class A1, class A2>
    inline
    auto
    invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2)
        -> decltype(((*boost::forward<A0>(a0)).*f)(boost::forward<A1>(a1), boost::forward<A2>(a2)))
    {
        return ((*boost::forward<A0>(a0)).*f)(boost::forward<A1>(a1), boost::forward<A2>(a2));
    }
    template <class R, class Fp, class A0, class A1, class A2>
    inline
    auto
    invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2)
        -> decltype(((*boost::forward<A0>(a0)).*f)(boost::forward<A1>(a1), boost::forward<A2>(a2)))
    {
        return ((*boost::forward<A0>(a0)).*f)(boost::forward<A1>(a1), boost::forward<A2>(a2));
    }

    // bullets 3 and 4

    template <class Fp, class A0>
    inline
    auto
    invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A0) a0)
        -> decltype(boost::forward<A0>(a0).*f)
    {
        return boost::forward<A0>(a0).*f;
    }
    template <class R, class Fp, class A0>
    inline
    auto
    invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A0) a0)
        -> decltype(boost::forward<A0>(a0).*f)
    {
        return boost::forward<A0>(a0).*f;
    }

    template <class Fp, class A0>
    inline
    auto
    invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A0) a0)
        -> decltype((*boost::forward<A0>(a0)).*f)
    {
        return (*boost::forward<A0>(a0)).*f;
    }
    template <class R, class Fp, class A0>
    inline
    auto
    invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A0) a0)
        -> decltype((*boost::forward<A0>(a0)).*f)
    {
        return (*boost::forward<A0>(a0)).*f;
    }

    // bullet 5

    template <class Fp>
    inline
    auto invoke(BOOST_THREAD_RV_REF(Fp) f)
    -> decltype(boost::forward<Fp>(f)())
    {
      return boost::forward<Fp>(f)();
    }
    template <class Fp, class A1>
    inline
    auto invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A1) a1)
    -> decltype(boost::forward<Fp>(f)(boost::forward<A1>(a1)))
    {
      return boost::forward<Fp>(f)(boost::forward<A1>(a1));
    }    template <class Fp, class A1, class A2>
    inline
    auto invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2)
    -> decltype(boost::forward<Fp>(f)(boost::forward<A1>(a1), boost::forward<A2>(a2)))
    {
      return boost::forward<Fp>(f)(boost::forward<A1>(a1), boost::forward<A2>(a2));
    }
    template <class Fp, class A1, class A2, class A3>
    inline
    auto invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2, BOOST_THREAD_RV_REF(A3) a3)
    -> decltype(boost::forward<Fp>(f)(boost::forward<A1>(a1), boost::forward<A2>(a2), boost::forward<A3>(a3)))
    {
      return boost::forward<Fp>(f)(boost::forward<A1>(a1), boost::forward<A2>(a2), boost::forward<A3>(a3));
    }

    template <class R, class Fp>
    inline
    auto invoke(BOOST_THREAD_RV_REF(Fp) f)
    -> decltype(boost::forward<Fp>(f)())
    {
      return boost::forward<Fp>(f)();
    }
    template <class R, class Fp, class A1>
    inline
    auto invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A1) a1)
    -> decltype(boost::forward<Fp>(f)(boost::forward<A1>(a1)))
    {
      return boost::forward<Fp>(f)(boost::forward<A1>(a1));
    }
    template <class R, class Fp, class A1, class A2>
    inline
    auto invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2)
    -> decltype(boost::forward<Fp>(f)(boost::forward<A1>(a1), boost::forward<A2>(a2)))
    {
      return boost::forward<Fp>(f)(boost::forward<A1>(a1), boost::forward<A2>(a2));
    }
    template <class R, class Fp, class A1, class A2, class A3>
    inline
    auto invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2, BOOST_THREAD_RV_REF(A3) a3)
    -> decltype(boost::forward<Fp>(f)(boost::forward<A1>(a1), boost::forward<A2>(a2), boost::forward<A3>(a3)))
    {
      return boost::forward<Fp>(f)(boost::forward<A1>(a1), boost::forward<A2>(a2), boost::forward<A3>(a3));
    }

#endif // BOOST_NO_CXX11_VARIADIC_TEMPLATES

#elif ! defined(BOOST_NO_SFINAE_EXPR) && \
    ! defined BOOST_NO_CXX11_HDR_FUNCTIONAL && \
    defined  BOOST_MSVC

//#error
    template <class Ret, class Fp>
    inline
    Ret invoke(BOOST_THREAD_RV_REF(Fp) f)
    {
      return f();
    }
    template <class Ret, class Fp, class A1>
    inline
    Ret invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A1) a1)
    {
      return std::bind(boost::forward<Fp>(f), boost::forward<A1>(a1))();
    }
    template <class Ret, class Fp, class A1, class A2>
    inline
    Ret invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2)
    {
      return std::bind(boost::forward<Fp>(f), boost::forward<A1>(a1), boost::forward<A2>(a2))();
    }
    template <class Ret, class Fp, class A1, class A2, class A3>
    inline
    Ret invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2, BOOST_THREAD_RV_REF(A3) a3)
    {
      return std::bind(boost::forward<Fp>(f), boost::forward<A1>(a1), boost::forward<A2>(a2), boost::forward<A3>(a3))();
    }

#define BOOST_THREAD_PROVIDES_INVOKE_RET

#elif ! defined  BOOST_MSVC
//!!!!!  WARNING !!!!! THIS DOESN'T WORKS YET
#define BOOST_THREAD_PROVIDES_INVOKE_RET

#if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)

    // bullet 1
    // (t1.*f)(t2, ..., tN) when f is a pointer to a member function of a class T and t1 is an object of
    // type T or a reference to an object of type T or a reference to an object of a type derived from T
    template <class Ret, class A, class A0, class ...Args>
    inline
    typename enable_if_c
    <
        is_base_of<A, typename remove_reference<A0>::type>::value,
        Ret
    >::type
    invoke(Ret (A::*f)(Args...), BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(Args) ...args)
    {
        return (boost::forward<A0>(a0).*f)(boost::forward<Args>(args)...);
    }

    template <class Ret, class A, class A0, class ...Args>
    inline
    typename enable_if_c
    <
        is_base_of<A, typename remove_reference<A0>::type>::value,
        Ret
    >::type
    invoke(Ret (A::*f)(Args...) const, BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(Args) ...args)
    {
        return (boost::forward<A0>(a0).*f)(boost::forward<Args>(args)...);
    }

    template <class Ret, class A, class A0, class ...Args>
    inline
    typename enable_if_c
    <
        is_base_of<A, typename remove_reference<A0>::type>::value,
        Ret
    >::type
    invoke(Ret (A::*f)(Args...) volatile, BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(Args) ...args)
    {
        return (boost::forward<A0>(a0).*f)(boost::forward<Args>(args)...);
    }

    template <class Ret, class A, class A0, class ...Args>
    inline
    typename enable_if_c
    <
        is_base_of<A, typename remove_reference<A0>::type>::value,
        Ret
    >::type
    invoke(Ret (A::*f)(Args...) const volatile, BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(Args) ...args)
    {
        return (boost::forward<A0>(a0).*f)(boost::forward<Args>(args)...);
    }

    // bullet 2
    // ((*t1).*f)(t2, ..., tN) when f is a pointer to a member function of a class T and t1 is not one of
    // the types described in the previous item;
    template <class Ret, class A, class A0, class ...Args>
    inline
    typename enable_if_c
    <
        ! is_base_of<A, typename remove_reference<A0>::type>::value,
        Ret
    >::type
    invoke(Ret (A::*f)(Args...), BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(Args) ...args)
    {
      return ((*boost::forward<A0>(a0)).*f)(boost::forward<Args>(args)...);
    }

    template <class Ret, class A, class A0, class ...Args>
    inline
    typename enable_if_c
    <
        ! is_base_of<A, typename remove_reference<A0>::type>::value,
        Ret
    >::type
    invoke(Ret (A::*f)(Args...) const, BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(Args) ...args)
    {
      return ((*boost::forward<A0>(a0)).*f)(boost::forward<Args>(args)...);
    }

    template <class Ret, class A, class A0, class ...Args>
    inline
    typename enable_if_c
    <
        ! is_base_of<A, typename remove_reference<A0>::type>::value,
        Ret
    >::type
    invoke(Ret (A::*f)(Args...) volatile, BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(Args) ...args)
    {
      return ((*boost::forward<A0>(a0)).*f)(boost::forward<Args>(args)...);
    }

    template <class Ret, class A, class A0, class ...Args>
    inline
    typename enable_if_c
    <
        ! is_base_of<A, typename remove_reference<A0>::type>::value,
        Ret
    >::type
    invoke(Ret (A::*f)(Args...) const volatile, BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(Args) ...args)
    {
      return ((*boost::forward<A0>(a0)).*f)(boost::forward<Args>(args)...);
    }

    // bullet 3
    // t1.*f when N == 1 and f is a pointer to member data of a class T and t1 is an object of type T or a
    // reference to an object of type T or a reference to an object of a type derived from T;
//    template <class Ret, class A, class A0>
//    inline
//    typename enable_if_c
//    <
//        is_base_of<A, typename remove_reference<A0>::type>::value,
//        typename detail::apply_cv<A0, A>::type&
//    >::type
//    invoke(Ret A::* f, BOOST_THREAD_RV_REF(A0) a0)
//    {
//        return boost::forward<A0>(a0).*f;
//    }

    // bullet 4
    // (*t1).*f when N == 1 and f is a pointer to member data of a class T and t1 is not one of the types
    //described in the previous item;

//    template <class A0, class Ret, bool>
//    struct d4th_helper
//    {
//    };
//
//    template <class A0, class Ret>
//    struct d4th_helper<A0, Ret, true>
//    {
//        typedef typename apply_cv<decltype(*declval<A0>()), Ret>::type type;
//    };
//
//    template <class Ret, class A, class A0>
//    inline
//    typename detail::4th_helper<A, Ret,
//                          !is_base_of<A,
//                                      typename remove_reference<A0>::type
//                                     >::value
//                         >::type&
//    invoke(Ret A::* f, BOOST_THREAD_RV_REF(A0) a0)
//    {
//        return (*boost::forward<A0>(a0)).*f;
//    }

//    template <class Ret, class A, class A0>
//    inline
//    typename enable_if_c
//    <
//        !is_base_of<A, typename remove_reference<A0>::type>::value,
//        typename detail::ref_return1<Ret A::*, A0>::type
//    >::type
//    invoke(Ret A::* f, BOOST_THREAD_RV_REF(A0) a0)
//    {
//        return (*boost::forward<A0>(a0)).*f;
//    }

    // bullet 5
    // f(t1, t2, ..., tN) in all other cases.

    template <class Ret, class Fp, class ...Args>
    inline Ret do_invoke(mpl::false_, BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(Args) ...args)
    {
      return boost::forward<Fp>(f)(boost::forward<Args>(args)...);
    }

    template <class Ret, class Fp, class ...Args>
    inline Ret do_invoke(mpl::true_, BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(Args) ...args)
    {
      return f(boost::forward<Args>(args)...);
    }

    template <class Ret, class Fp, class ...Args>
    inline
    typename disable_if_c
    <
        is_member_function_pointer<Fp>::value,
        Ret
    >::type
    invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(Args) ...args)
    {
      return boost::detail::do_invoke<Ret>(boost::is_pointer<Fp>(), boost::forward<Fp>(f), boost::forward<Args>(args)...);
    }
#else // BOOST_NO_CXX11_VARIADIC_TEMPLATES
    // bullet 1
    // (t1.*f)(t2, ..., tN) when f is a pointer to a member function of a class T and t1 is an object of
    // type T or a reference to an object of type T or a reference to an object of a type derived from T

    template <class Ret, class A, class A0>
    inline
    typename enable_if_c
    <
        is_base_of<A, typename remove_reference<A0>::type>::value,
        Ret
    >::type
    invoke(Ret (A::*f)(), A0& a0)
    {
        return (a0.*f)();
    }
    template <class Ret, class A, class A0>
    inline
    typename enable_if_c
    <
        is_base_of<A, typename remove_reference<A0>::type>::value,
        Ret
    >::type
    invoke(Ret (A::*f)(), A0* a0)
    {
        return ((*a0).*f)();
    }

    template <class Ret, class A, class A0, class A1>
    inline
    typename enable_if_c
    <
        is_base_of<A, typename remove_reference<A0>::type>::value,
        Ret
    >::type
    invoke(Ret (A::*f)(A1),
        A0& a0, BOOST_THREAD_RV_REF(A1) a1
        )
    {
        return (a0.*f)(boost::forward<A1>(a1));
    }
    template <class Ret, class A, class A0, class A1>
    inline
    typename enable_if_c
    <
        is_base_of<A, typename remove_reference<A0>::type>::value,
        Ret
    >::type
    invoke(Ret (A::*f)(A1), A0& a0, A1 a1)
    {
        return (a0.*f)(a1);
    }
    template <class Ret, class A, class A0, class A1>
    inline
    typename enable_if_c
    <
        is_base_of<A, typename remove_reference<A0>::type>::value,
        Ret
    >::type
    invoke(Ret (A::*f)(A1), A0* a0, BOOST_THREAD_RV_REF(A1) a1
        )
    {
        return (*(a0).*f)(boost::forward<A1>(a1));
    }
    template <class Ret, class A, class A0, class A1>
    inline
    typename enable_if_c
    <
        is_base_of<A, typename remove_reference<A0>::type>::value,
        Ret
    >::type
    invoke(Ret (A::*f)(A1), A0* a0, A1 a1)
    {
        return (*a0.*f)(a1);
    }
    template <class Ret, class A, class A0, class A1, class A2>
    inline
    typename enable_if_c
    <
        is_base_of<A, typename remove_reference<A0>::type>::value,
        Ret
    >::type
    invoke(Ret (A::*f)(A1, A2),
        A0& a0, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2
        )
    {
        return (a0.*f)(boost::forward<A1>(a1), boost::forward<A2>(a2));
    }
    template <class Ret, class A, class A0, class A1, class A2>
    inline
    typename enable_if_c
    <
        is_base_of<A, typename remove_reference<A0>::type>::value,
        Ret
    >::type
    invoke(Ret (A::*f)(A1, A2), A0* a0, A1 a1, A2 a2)
    {
        return ((*a0).*f)(a1, a2);
    }
    template <class Ret, class A, class A0, class A1, class A2, class A3>
    inline
    typename enable_if_c
    <
        is_base_of<A, typename remove_reference<A0>::type>::value,
        Ret
    >::type
    invoke(Ret (A::*f)(A1, A2, A3),
        A0& a0, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2, BOOST_THREAD_RV_REF(A3) a3)
    {
        return (a0.*f)(boost::forward<A1>(a1), boost::forward<A2>(a2), boost::forward<A3>(a3));
    }
    template <class Ret, class A, class A0, class A1, class A2, class A3>
    inline
    typename enable_if_c
    <
        is_base_of<A, typename remove_reference<A0>::type>::value,
        Ret
    >::type
    invoke(Ret (A::*f)(A1, A2, A3), A0* a0, A1 a1, A2 a2, A3 a3)
    {
        return ((*a0).*f)(a1, a2, a3);
    }

///
    template <class Ret, class A, class A0>
    inline
    typename enable_if_c
    <
        is_base_of<A, typename remove_reference<A0>::type>::value,
        Ret
    >::type
    invoke(Ret (A::*f)() const, A0 const& a0)
    {
        return (a0.*f)();
    }
    template <class Ret, class A, class A0>
    inline
    typename enable_if_c
    <
        is_base_of<A, typename remove_reference<A0>::type>::value,
        Ret
    >::type
    invoke(Ret (A::*f)() const, A0 const* a0)
    {
        return ((*a0).*f)();
    }
    template <class Ret, class A, class A0, class A1>
    inline
    typename enable_if_c
    <
        is_base_of<A, typename remove_reference<A0>::type>::value,
        Ret
    >::type
    invoke(Ret (A::*f)(A1) const, A0 const& a0, BOOST_THREAD_RV_REF(A1) a1)
    {
        return (a0.*f)(boost::forward<A1>(a1));
    }
    template <class Ret, class A, class A0, class A1>
    inline
    typename enable_if_c
    <
        is_base_of<A, typename remove_reference<A0>::type>::value,
        Ret
    >::type
    invoke(Ret (A::*f)(A1) const, A0 const* a0, BOOST_THREAD_RV_REF(A1) a1)
    {
        return ((*a0).*f)(boost::forward<A1>(a1));
    }

    template <class Ret, class A, class A0, class A1>
    inline
    typename enable_if_c
    <
        is_base_of<A, typename remove_reference<A0>::type>::value,
        Ret
    >::type
    invoke(Ret (A::*f)(A1) const, A0 const& a0, A1 a1)
    {
        return (a0.*f)(a1);
    }
    template <class Ret, class A, class A0, class A1, class A2>
    inline
    typename enable_if_c
    <
        is_base_of<A, typename remove_reference<A0>::type>::value,
        Ret
    >::type
    invoke(Ret (A::*f)(A1, A2) const,
        A0 const& a0, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2
        )
    {
        return (boost::forward<A0>(a0).*f)(boost::forward<A1>(a1), boost::forward<A2>(a2)
            );
    }
    template <class Ret, class A, class A0, class A1, class A2>
    inline
    typename enable_if_c
    <
        is_base_of<A, typename remove_reference<A0>::type>::value,
        Ret
    >::type
    invoke(Ret (A::*f)(A1, A2) const, A0 const& a0, A1 a1, A2 a2)
    {
        return (a0.*f)(a1, a2);
    }
    template <class Ret, class A, class A0, class A1, class A2, class A3>
    inline
    typename enable_if_c
    <
        is_base_of<A, typename remove_reference<A0>::type>::value,
        Ret
    >::type
    invoke(Ret (A::*f)(A1, A2, A3) const,
        BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2, BOOST_THREAD_RV_REF(A3) a3
        )
    {
        return (boost::forward<A0>(a0).*f)(boost::forward<A1>(a1), boost::forward<A2>(a2), boost::forward<A3>(a3));
    }
    template <class Ret, class A, class A0, class A1, class A2, class A3>
    inline
    typename enable_if_c
    <
        is_base_of<A, typename remove_reference<A0>::type>::value,
        Ret
    >::type
    invoke(Ret (A::*f)(A1, A2, A3) const, A0 a0, A1 a1, A2 a2, A3 a3)
    {
        return (a0.*f)(a1, a2, a3);
    }
    ///
    template <class Ret, class A, class A0>
    inline
    typename enable_if_c
    <
        is_base_of<A, typename remove_reference<A0>::type>::value,
        Ret
    >::type
    invoke(Ret (A::*f)() volatile, BOOST_THREAD_RV_REF(A0) a0)
    {
        return (boost::forward<A0>(a0).*f)();
    }
    template <class Ret, class A, class A0, class A1>
    inline
    typename enable_if_c
    <
        is_base_of<A, typename remove_reference<A0>::type>::value,
        Ret
    >::type
    invoke(Ret (A::*f)(A1) volatile, BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(A1) a1)
    {
        return (boost::forward<A0>(a0).*f)(boost::forward<A1>(a1));
    }
    template <class Ret, class A, class A0, class A1>
    inline
    typename enable_if_c
    <
        is_base_of<A, typename remove_reference<A0>::type>::value,
        Ret
    >::type
    invoke(Ret (A::*f)(A1) volatile, A0 a0, A1 a1)
    {
        return (a0.*f)(a1);
    }
    template <class Ret, class A, class A0, class A1, class A2>
    inline
    typename enable_if_c
    <
        is_base_of<A, typename remove_reference<A0>::type>::value,
        Ret
    >::type
    invoke(Ret (A::*f)(A1, A2) volatile,
        BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2)
    {
        return (boost::forward<A0>(a0).*f)(boost::forward<A1>(a1), boost::forward<A2>(a2));
    }
    template <class Ret, class A, class A0, class A1, class A2>
    inline
    typename enable_if_c
    <
        is_base_of<A, typename remove_reference<A0>::type>::value,
        Ret
    >::type
    invoke(Ret (A::*f)(A1, A2) volatile, A0 a0, A1 a1, A2 a2 )
    {
        return (a0.*f)(a1, a2);
    }
    template <class Ret, class A, class A0, class A1, class A2, class A3>
    inline
    typename enable_if_c
    <
        is_base_of<A, typename remove_reference<A0>::type>::value,
        Ret
    >::type
    invoke(Ret (A::*f)(A1, A2, A3) volatile,
        BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2, BOOST_THREAD_RV_REF(A3) a3
        )
    {
        return (boost::forward<A0>(a0).*f)(boost::forward<A1>(a1), boost::forward<A2>(a2), boost::forward<A3>(a3));
    }
    template <class Ret, class A, class A0, class A1, class A2, class A3>
    inline
    typename enable_if_c
    <
        is_base_of<A, typename remove_reference<A0>::type>::value,
        Ret
    >::type
    invoke(Ret (A::*f)(A1, A2, A3) volatile, A0 a0, A1 a1, A2 a2, A3 a3)
    {
        return (a0.*f)(a1, a2, a3);
    }
    ///
    template <class Ret, class A, class A0>
    inline
    typename enable_if_c
    <
        is_base_of<A, typename remove_reference<A0>::type>::value,
        Ret
    >::type
    invoke(Ret (A::*f)() const volatile, BOOST_THREAD_RV_REF(A0) a0)
    {
        return (boost::forward<A0>(a0).*f)();
    }
    template <class Ret, class A, class A0, class A1>
    inline
    typename enable_if_c
    <
        is_base_of<A, typename remove_reference<A0>::type>::value,
        Ret
    >::type
    invoke(Ret (A::*f)(A1) const volatile, BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(A1) a1)
    {
        return (boost::forward<A0>(a0).*f)(boost::forward<A1>(a1));
    }
    template <class Ret, class A, class A0, class A1>
    inline
    typename enable_if_c
    <
        is_base_of<A, typename remove_reference<A0>::type>::value,
        Ret
    >::type
    invoke(Ret (A::*f)(A1) const volatile, A0 a0, A1 a1)
    {
        return (a0.*f)(a1);
    }
    template <class Ret, class A, class A0, class A1, class A2>
    inline
    typename enable_if_c
    <
        is_base_of<A, typename remove_reference<A0>::type>::value,
        Ret
    >::type
    invoke(Ret (A::*f)(A1, A2) const volatile,
        BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2
        )
    {
        return (boost::forward<A0>(a0).*f)(boost::forward<A1>(a1), boost::forward<A2>(a2));
    }
    template <class Ret, class A, class A0, class A1, class A2>
    inline
    typename enable_if_c
    <
        is_base_of<A, typename remove_reference<A0>::type>::value,
        Ret
    >::type
    invoke(Ret (A::*f)(A1, A2) const volatile,
        A0 a0, A1 a1, A2 a2
        )
    {
        return (a0.*f)(a1, a2);
    }
    template <class Ret, class A, class A0, class A1, class A2, class A3>
    inline
    typename enable_if_c
    <
        is_base_of<A, typename remove_reference<A0>::type>::value,
        Ret
    >::type
    invoke(Ret (A::*f)(A1, A2, A3) const volatile,
        BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2, BOOST_THREAD_RV_REF(A3) a3
        )
    {
        return (boost::forward<A0>(a0).*f)(boost::forward<A1>(a1), boost::forward<A2>(a2), boost::forward<A3>(a3));
    }
    template <class Ret, class A, class A0, class A1, class A2, class A3>
    inline
    typename enable_if_c
    <
        is_base_of<A, typename remove_reference<A0>::type>::value,
        Ret
    >::type
    invoke(Ret (A::*f)(A1, A2, A3) const volatile,
        A0 a0, A1 a1, A2 a2, A3 a3
        )
    {
        return (a0.*f)(a1, a2, a3);
    }

    // bullet 2
    // ((*t1).*f)(t2, ..., tN) when f is a pointer to a member function of a class T and t1 is not one of
    // the types described in the previous item;
    template <class Ret, class A, class A0>
    inline
    typename enable_if_c
    <
        ! is_base_of<A, typename remove_reference<A0>::type>::value,
        Ret
    >::type
    invoke(Ret (A::*f)(), BOOST_THREAD_RV_REF(A0) a0)
    {
      return ((*boost::forward<A0>(a0)).*f)();
    }
    template <class Ret, class A, class A0, class A1>
    inline
    typename enable_if_c
    <
        ! is_base_of<A, typename remove_reference<A0>::type>::value,
        Ret
    >::type
    invoke(Ret (A::*f)(A1), BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(A1) a1)
    {
      return ((*boost::forward<A0>(a0)).*f)(boost::forward<A1>(a1));
    }
    template <class Ret, class A, class A0, class A1>
    inline
    typename enable_if_c
    <
        ! is_base_of<A, typename remove_reference<A0>::type>::value,
        Ret
    >::type
    invoke(Ret (A::*f)(A1), A0 a0, A1 a1)
    {
      return ((*a0).*f)(a1);
    }
    template <class Ret, class A, class A0, class A1, class A2>
    inline
    typename enable_if_c
    <
        ! is_base_of<A, typename remove_reference<A0>::type>::value,
        Ret
    >::type
    invoke(Ret (A::*f)(A1, BOOST_THREAD_RV_REF(A2)),
        BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2)
    {
      return ((*boost::forward<A0>(a0)).*f)(boost::forward<A1>(a1), boost::forward<A2>(a2));
    }
    template <class Ret, class A, class A0, class A1, class A2>
    inline
    typename enable_if_c
    <
        ! is_base_of<A, typename remove_reference<A0>::type>::value,
        Ret
    >::type
    invoke(Ret (A::*f)(A1, A2), A0 a0, A1 a1, A2 a2)
    {
      return ((*a0).*f)(a1, a2);
    }
    template <class Ret, class A, class A0, class A1, class A2, class A3>
    inline
    typename enable_if_c
    <
        ! is_base_of<A, typename remove_reference<A0>::type>::value,
        Ret
    >::type
    invoke(Ret (A::*f)(A1, BOOST_THREAD_RV_REF(A2), BOOST_THREAD_RV_REF(A3)),
        BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2, BOOST_THREAD_RV_REF(A3) a3)
    {
      return ((*boost::forward<A0>(a0)).*f)(boost::forward<A1>(a1), boost::forward<A2>(a2), boost::forward<A3>(a3)
          );
    }
    template <class Ret, class A, class A0, class A1, class A2, class A3>
    inline
    typename enable_if_c
    <
        ! is_base_of<A, typename remove_reference<A0>::type>::value,
        Ret
    >::type
    invoke(Ret (A::*f)(A1, A2, A3), A0 a0, A1 a1, A2 a2, A3 a3)
    {
      return ((*a0).*f)(a1, a2, a3);
    }

///
    template <class Ret, class A, class A0>
    inline
    typename enable_if_c
    <
        ! is_base_of<A, typename remove_reference<A0>::type>::value,
        Ret
    >::type
    invoke(Ret (A::*f)() const, BOOST_THREAD_RV_REF(A0) a0)
    {
      return ((*boost::forward<A0>(a0)).*f)();
    }
    template <class Ret, class A, class A0, class A1>
    inline
    typename enable_if_c
    <
        ! is_base_of<A, typename remove_reference<A0>::type>::value,
        Ret
    >::type
    invoke(Ret (A::*f)(A1) const,
        BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(A1) a1)
    {
      return ((*boost::forward<A0>(a0)).*f)(boost::forward<A1>(a1));
    }
    template <class Ret, class A, class A0, class A1>
    inline
    typename enable_if_c
    <
        ! is_base_of<A, typename remove_reference<A0>::type>::value,
        Ret
    >::type
    invoke(Ret (A::*f)(A1) const, BOOST_THREAD_RV_REF(A0) a0, A1 a1)
    {
      return ((*boost::forward<A0>(a0)).*f)(a1);
    }
    template <class Ret, class A, class A0, class A1>
    inline
    typename enable_if_c
    <
        ! is_base_of<A, typename remove_reference<A0>::type>::value,
        Ret
    >::type
    invoke(Ret (A::*f)(A1) const, A0 a0, A1 a1)
    {
      return ((*a0).*f)(a1);
    }
    template <class Ret, class A, class A0, class A1, class A2>
    inline
    typename enable_if_c
    <
        ! is_base_of<A, typename remove_reference<A0>::type>::value,
        Ret
    >::type
    invoke(Ret (A::*f)(A1, A2) const,
        BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2)
    {
      return ((*boost::forward<A0>(a0)).*f)(boost::forward<A1>(a1), boost::forward<A2>(a2));
    }
    template <class Ret, class A, class A0, class A1, class A2>
    inline
    typename enable_if_c
    <
        ! is_base_of<A, typename remove_reference<A0>::type>::value,
        Ret
    >::type
    invoke(Ret (A::*f)(A1, A2) const, A0 a0, A1 a1, A2 a2)
    {
      return ((*a0).*f)(a1, a2);
    }
    template <class Ret, class A, class A0, class A1, class A2, class A3>
    inline
    typename enable_if_c
    <
        ! is_base_of<A, typename remove_reference<A0>::type>::value,
        Ret
    >::type
    invoke(Ret (A::*f)(A1, A2, A3) const,
        BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2, BOOST_THREAD_RV_REF(A3) a3)
    {
      return ((*boost::forward<A0>(a0)).*f)(boost::forward<A1>(a1), boost::forward<A2>(a2), boost::forward<A3>(a3));
    }
    template <class Ret, class A, class A0, class A1, class A2, class A3>
    inline
    typename enable_if_c
    <
        ! is_base_of<A, typename remove_reference<A0>::type>::value,
        Ret
    >::type
    invoke(Ret (A::*f)(A1, A2, A3) const,
        A0 a0, A1 a1, A2 a2, A3 a3)
    {
      return ((*a0).*f)(a1, a2, a3);
    }
    ///
    template <class Ret, class A, class A0>
    inline
    typename enable_if_c
    <
        ! is_base_of<A, typename remove_reference<A0>::type>::value,
        Ret
    >::type
    invoke(Ret (A::*f)() volatile, BOOST_THREAD_RV_REF(A0) a0)
    {
      return ((*boost::forward<A0>(a0)).*f)();
    }
    template <class Ret, class A, class A0, class A1>
    inline
    typename enable_if_c
    <
        ! is_base_of<A, typename remove_reference<A0>::type>::value,
        Ret
    >::type
    invoke(Ret (A::*f)(A1) volatile,
        BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(A1) a1)
    {
      return ((*boost::forward<A0>(a0)).*f)(boost::forward<A1>(a1));
    }
    template <class Ret, class A, class A0, class A1>
    inline
    typename enable_if_c
    <
        ! is_base_of<A, typename remove_reference<A0>::type>::value,
        Ret
    >::type
    invoke(Ret (A::*f)(A1) volatile, A0 a0, A1 a1)
    {
      return ((*a0).*f)(a1);
    }
    template <class Ret, class A, class A0, class A1, class A2>
    inline
    typename enable_if_c
    <
        ! is_base_of<A, typename remove_reference<A0>::type>::value,
        Ret
    >::type
    invoke(Ret (A::*f)(A1, A2) volatile,
        BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2)
    {
      return ((*boost::forward<A0>(a0)).*f)(boost::forward<A1>(a1), boost::forward<A2>(a2));
    }
    template <class Ret, class A, class A0, class A1, class A2>
    inline
    typename enable_if_c
    <
        ! is_base_of<A, typename remove_reference<A0>::type>::value,
        Ret
    >::type
    invoke(Ret (A::*f)(A1, A2) volatile, A0 a0, A1 a1, A2 a2)
    {
      return ((*a0).*f)(a1, a2);
    }
    template <class Ret, class A, class A0, class A1, class A2, class A3>
    inline
    typename enable_if_c
    <
        ! is_base_of<A, typename remove_reference<A0>::type>::value,
        Ret
    >::type
    invoke(Ret (A::*f)(A1, A2, A3) volatile,
        BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2, BOOST_THREAD_RV_REF(A3) a3)
    {
      return ((*boost::forward<A0>(a0)).*f)(boost::forward<A1>(a1), boost::forward<A2>(a2), boost::forward<A3>(a3));
    }
    template <class Ret, class A, class A0, class A1, class A2, class A3>
    inline
    typename enable_if_c
    <
        ! is_base_of<A, typename remove_reference<A0>::type>::value,
        Ret
    >::type
    invoke(Ret (A::*f)(A1, A2, A3) volatile, A0 a0, A1 a1, A2 a2, A3 a3)
    {
      return ((*a0).*f)(a1, a2, a3);
    }
    ///
    template <class Ret, class A, class A0>
    inline
    typename enable_if_c
    <
        ! is_base_of<A, typename remove_reference<A0>::type>::value,
        Ret
    >::type
    invoke(Ret (A::*f)() const volatile, BOOST_THREAD_RV_REF(A0) a0)
    {
      return ((*boost::forward<A0>(a0)).*f)();
    }
    template <class Ret, class A, class A0>
    inline
    typename enable_if_c
    <
        ! is_base_of<A, typename remove_reference<A0>::type>::value,
        Ret
    >::type
    invoke(Ret (A::*f)() const volatile, A0 a0)
    {
      return ((*a0).*f)();
    }
    template <class Ret, class A, class A0, class A1>
    inline
    typename enable_if_c
    <
        ! is_base_of<A, typename remove_reference<A0>::type>::value,
        Ret
    >::type
    invoke(Ret (A::*f)(A1) const volatile,
        BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(A1) a1)
    {
      return ((*boost::forward<A0>(a0)).*f)(boost::forward<A1>(a1));
    }
    template <class Ret, class A, class A0, class A1>
    inline
    typename enable_if_c
    <
        ! is_base_of<A, typename remove_reference<A0>::type>::value,
        Ret
    >::type
    invoke(Ret (A::*f)(A1) const volatile, A0 a0, A1 a1)
    {
      return ((*a0).*f)(a1);
    }
    template <class Ret, class A, class A0, class A1, class A2>
    inline
    typename enable_if_c
    <
        ! is_base_of<A, typename remove_reference<A0>::type>::value,
        Ret
    >::type
    invoke(Ret (A::*f)(A1, A2) const volatile,
        BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2)
    {
      return ((*boost::forward<A0>(a0)).*f)(boost::forward<A1>(a1), boost::forward<A2>(a2));
    }
    template <class Ret, class A, class A0, class A1, class A2>
    inline
    typename enable_if_c
    <
        ! is_base_of<A, typename remove_reference<A0>::type>::value,
        Ret
    >::type
    invoke(Ret (A::*f)(A1, A2) const volatile,
        A0 a0, A1 a1, A2 a2)
    {
      return ((*a0).*f)(a1, a2);
    }
    template <class Ret, class A, class A0, class A1, class A2, class A3>
    inline
    typename enable_if_c
    <
        ! is_base_of<A, typename remove_reference<A0>::type>::value,
        Ret
    >::type
    invoke(Ret (A::*f)(A1, A2, A3) const volatile,
        BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2, BOOST_THREAD_RV_REF(A3) a3)
    {
      return ((*boost::forward<A0>(a0)).*f)(boost::forward<A1>(a1), boost::forward<A2>(a2), boost::forward<A3>(a3));
    }
    template <class Ret, class A, class A0, class A1, class A2, class A3>
    inline
    typename enable_if_c
    <
        ! is_base_of<A, typename remove_reference<A0>::type>::value,
        Ret
    >::type
    invoke(Ret (A::*f)(A1, A2, A3) const volatile,
        A0 a0, A1 a1, A2 a2, A3 a3)
    {
      return ((*a0).*f)(a1, a2, a3);
    }
    // bullet 3
    // t1.*f when N == 1 and f is a pointer to member data of a class T and t1 is an object of type T or a
    // reference to an object of type T or a reference to an object of a type derived from T;
//    template <class Ret, class A, class A0>
//    inline
//    typename enable_if_c
//    <
//        is_base_of<A, typename remove_reference<A0>::type>::value,
//        typename detail::apply_cv<A0, A>::type&
//    >::type
//    invoke(Ret A::* f, BOOST_THREAD_RV_REF(A0) a0)
//    {
//        return boost::forward<A0>(a0).*f;
//    }

    // bullet 4
    // (*t1).*f when N == 1 and f is a pointer to member data of a class T and t1 is not one of the types
    //described in the previous item;

//    template <class A0, class Ret, bool>
//    struct d4th_helper
//    {
//    };
//
//    template <class A0, class Ret>
//    struct d4th_helper<A0, Ret, true>
//    {
//        typedef typename apply_cv<decltype(*declval<A0>()), Ret>::type type;
//    };
//
//    template <class Ret, class A, class A0>
//    inline
//    typename detail::4th_helper<A, Ret,
//                          !is_base_of<A,
//                                      typename remove_reference<A0>::type
//                                     >::value
//                         >::type&
//    invoke(Ret A::* f, BOOST_THREAD_RV_REF(A0) a0)
//    {
//        return (*boost::forward<A0>(a0)).*f;
//    }

//    template <class Ret, class A, class A0>
//    inline
//    typename enable_if_c
//    <
//        !is_base_of<A, typename remove_reference<A0>::type>::value,
//        typename detail::ref_return1<Ret A::*, A0>::type
//    >::type
//    invoke(Ret A::* f, BOOST_THREAD_RV_REF(A0) a0)
//    {
//        return (*boost::forward<A0>(a0)).*f;
//    }

    // bullet 5
    // f(t1, t2, ..., tN) in all other cases.

    template <class Ret, class Fp>
    inline Ret do_invoke(mpl::false_, BOOST_THREAD_FWD_REF(Fp) f)
    {
      return boost::forward<Fp>(f)();
    }
    template <class Ret, class Fp>
    inline Ret do_invoke(mpl::true_, BOOST_THREAD_FWD_REF(Fp) f)
    {
      return f();
    }
    template <class Ret, class Fp>
    inline
    typename disable_if_c
    <
        is_member_function_pointer<Fp>::value,
        Ret
    >::type
    invoke(BOOST_THREAD_FWD_REF(Fp) f)
    {
      return boost::detail::do_invoke<Ret>(boost::is_pointer<Fp>(), boost::forward<Fp>(f));
    }

    template <class Ret, class Fp, class A1>
    inline Ret do_invoke(mpl::false_, BOOST_THREAD_FWD_REF(Fp) f, BOOST_THREAD_RV_REF(A1) a1)
    {
      return boost::forward<Fp>(f)(boost::forward<A1>(a1));
    }
    template <class Ret, class Fp, class A1>
    inline Ret do_invoke(mpl::true_, BOOST_THREAD_FWD_REF(Fp) f, BOOST_THREAD_RV_REF(A1) a1)
    {
      return f(boost::forward<A1>(a1));
    }
    template <class Ret, class Fp, class A1>
    inline
    typename disable_if_c
    <
        is_member_function_pointer<Fp>::value,
        Ret
    >::type
    invoke(BOOST_THREAD_FWD_REF(Fp) f, BOOST_THREAD_RV_REF(A1) a1)
    {
      return boost::detail::do_invoke<Ret>(boost::is_pointer<Fp>(), boost::forward<Fp>(f), boost::forward<A1>(a1));
    }

    template <class Ret, class Fp, class A1, class A2>
    inline Ret do_invoke(mpl::false_, BOOST_THREAD_FWD_REF(Fp) f, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2)
    {
      return boost::forward<Fp>(f)(boost::forward<A1>(a1), boost::forward<A2>(a2));
    }
    template <class Ret, class Fp, class A1, class A2>
    inline Ret do_invoke(mpl::true_, BOOST_THREAD_FWD_REF(Fp) f, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2)
    {
      return f(boost::forward<A1>(a1), boost::forward<A2>(a2));
    }
    template <class Ret, class Fp, class A1, class A2>
    inline
    typename disable_if_c
    <
        is_member_function_pointer<Fp>::value,
        Ret
    >::type
    invoke(BOOST_THREAD_FWD_REF(Fp) f, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2)
    {
      return boost::detail::do_invoke<Ret>(boost::is_pointer<Fp>(), boost::forward<Fp>(f), boost::forward<A1>(a1), boost::forward<A2>(a2));
    }

    template <class Ret, class Fp, class A1, class A2, class A3>
    inline Ret do_invoke(mpl::false_, BOOST_THREAD_FWD_REF(Fp) f, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2, BOOST_THREAD_RV_REF(A3) a3)
    {
      return boost::forward<Fp>(f)(boost::forward<A1>(a1), boost::forward<A2>(a2), boost::forward<A3>(a3));
    }
    template <class Ret, class Fp, class A1, class A2, class A3>
    inline Ret do_invoke(mpl::true_, BOOST_THREAD_FWD_REF(Fp) f, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2, BOOST_THREAD_RV_REF(A3) a3)
    {
      return f(boost::forward<A1>(a1), boost::forward<A2>(a2), boost::forward<A3>(a3));
    }
    template <class Ret, class Fp, class A1, class A2, class A3>
    inline
    typename disable_if_c
    <
        is_member_function_pointer<Fp>::value,
        Ret
    >::type
    invoke(BOOST_THREAD_FWD_REF(Fp) f, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2, BOOST_THREAD_RV_REF(A3) a3)
    {
      return boost::detail::do_invoke<Ret>(boost::is_pointer<Fp>(), boost::forward<Fp>(f), boost::forward<A1>(a1), boost::forward<A2>(a2), boost::forward<A3>(a3));
    }

    template <class Ret, class Fp, class A1>
    inline Ret do_invoke(mpl::false_, BOOST_THREAD_FWD_REF(Fp) f, A1 a1)
    {
      return boost::forward<Fp>(f)(a1);
    }
    template <class Ret, class Fp, class A1>
    inline Ret do_invoke(mpl::true_, BOOST_THREAD_FWD_REF(Fp) f, A1 a1)
    {
      return f(a1);
    }
    template <class Ret, class Fp, class A1>
    inline
    typename disable_if_c
    <
        is_member_function_pointer<Fp>::value,
        Ret
    >::type
    invoke(BOOST_THREAD_FWD_REF(Fp) f, A1 a1)
    {
      return boost::detail::do_invoke<Ret>(boost::is_pointer<Fp>(), boost::forward<Fp>(f), a1);
    }

    template <class Ret, class Fp, class A1, class A2>
    inline Ret do_invoke(mpl::false_, BOOST_THREAD_FWD_REF(Fp) f, A1 a1, A2 a2)
    {
      return boost::forward<Fp>(f)(a1, a2);
    }
    template <class Ret, class Fp, class A1, class A2>
    inline Ret do_invoke(mpl::true_, BOOST_THREAD_FWD_REF(Fp) f, A1 a1, A2 a2)
    {
      return f(a1, a2);
    }
    template <class Ret, class Fp, class A1, class A2>
    inline
    typename disable_if_c
    <
        is_member_function_pointer<Fp>::value,
        Ret
    >::type
    invoke(BOOST_THREAD_FWD_REF(Fp) f, A1 a1, A2 a2)
    {
      return boost::detail::do_invoke<Ret>(boost::is_pointer<Fp>(), boost::forward<Fp>(f), a1, a2);
    }

    template <class Ret, class Fp, class A1, class A2, class A3>
    inline Ret do_invoke(mpl::false_, BOOST_THREAD_FWD_REF(Fp) f, A1 a1, A2 a2, A3 a3)
    {
      return boost::forward<Fp>(f)(a1, a2, a3);
    }
    template <class Ret, class Fp, class A1, class A2, class A3>
    inline Ret do_invoke(mpl::true_, BOOST_THREAD_FWD_REF(Fp) f, A1 a1, A2 a2, A3 a3)
    {
      return f(a1, a2, a3);
    }
    template <class Ret, class Fp, class A1, class A2, class A3>
    inline
    typename disable_if_c
    <
        is_member_function_pointer<Fp>::value,
        Ret
    >::type
    invoke(BOOST_THREAD_FWD_REF(Fp) f, A1 a1, A2 a2, A3 a3)
    {
      return boost::detail::do_invoke<Ret>(boost::is_pointer<Fp>(), boost::forward<Fp>(f), a1, a2, a3);
    }

    ///
    template <class Ret, class Fp>
    inline
    typename disable_if_c
    <
        is_member_function_pointer<Fp>::value,
        Ret
    >::type
    invoke(Fp &f)
    {
      return f();
    }
    template <class Ret, class Fp, class A1>
    inline
    typename disable_if_c
    <
        is_member_function_pointer<Fp>::value,
        Ret
    >::type
    invoke(Fp &f, BOOST_THREAD_RV_REF(A1) a1)
    {
      return f(boost::forward<A1>(a1));
    }
    template <class Ret, class Fp, class A1>
    inline
    typename disable_if_c
    <
        is_member_function_pointer<Fp>::value,
        Ret
    >::type
    invoke(Fp &f, A1 a1)
    {
      return f(a1);
    }
    template <class Ret, class Fp, class A1, class A2>
    inline
    typename disable_if_c
    <
        is_member_function_pointer<Fp>::value,
        Ret
    >::type
    invoke(Fp &f, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2)
    {
      return f(boost::forward<A1>(a1), boost::forward<A2>(a2));
    }
    template <class Ret, class Fp, class A1, class A2>
    inline
    typename disable_if_c
    <
        is_member_function_pointer<Fp>::value,
        Ret
    >::type
    invoke(Fp &f, A1 a1, A2 a2)
    {
      return f(a1, a2);
    }
    template <class Ret, class Fp, class A1, class A2, class A3>
    inline
    typename disable_if_c
    <
        is_member_function_pointer<Fp>::value,
        Ret
    >::type
    invoke(Fp &f, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2, BOOST_THREAD_RV_REF(A3) a3)
    {
      return f(boost::forward<A1>(a1), boost::forward<A2>(a2), boost::forward<A3>(a3));
    }
    template <class Ret, class Fp, class A1, class A2, class A3>
    inline
    typename disable_if_c
    <
        is_member_function_pointer<Fp>::value,
        Ret
    >::type
    invoke(Fp &f, A1 a1, A2 a2, A3 a3)
    {
      return f(a1, a2, a3);
    }
    ///

#endif // BOOST_NO_CXX11_VARIADIC_TEMPLATES

#endif  // all
      }
    }

#endif // header

max_stars_repo_name: bowlofstew/omim

max_issues_repo_name: wujf/mongo

max_forks_repo_name: wujf/mongo


text:
#include <QApplication>
#include <QMessageBox>
#include <QCommandLineParser>

#include "RegardRGBDMainWindow.h"

#include <Eigen/Core>

#include <osgDB/Registry>

#if defined(OSG_LIBRARY_STATIC)
// Add references for static linking some plugins
USE_OSGPLUGIN(ive)
USE_OSGPLUGIN(osg)
USE_OSGPLUGIN(osg2)
USE_OSGPLUGIN(rgb)
//USE_OSGPLUGIN(freetype)
USE_OSGPLUGIN(p3d)
USE_OSGPLUGIN(obj)
USE_OSGPLUGIN(osgViewer)
USE_OSGPLUGIN(ply)
//USE_OSGPLUGIN(png)
//USE_OSGPLUGIN(jpeg)

USE_DOTOSGWRAPPER_LIBRARY(osg)
USE_DOTOSGWRAPPER_LIBRARY(osgText)
USE_DOTOSGWRAPPER_LIBRARY(osgViewer)

USE_SERIALIZER_WRAPPER_LIBRARY(osg)
USE_SERIALIZER_WRAPPER_LIBRARY(osgManipulator)
USE_SERIALIZER_WRAPPER_LIBRARY(osgText)
#endif

int main(int argc, char** argv)
{
	Eigen::initParallel();

	// Qt Stuff
	QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
	QGuiApplication::setAttribute(Qt::AA_UseHighDpiPixmaps);

	QApplication app(argc, argv);

	QCoreApplication::setApplicationName(QStringLiteral("RegardRGBD"));
	QCoreApplication::setApplicationVersion(QStringLiteral("1.0"));

	// Create main window
	RegardRGBDMainWindow regardRGBDMainWindow;
	regardRGBDMainWindow.show();

	// Run application
	int returnValue = 0;
	try
	{
		returnValue = app.exec();
	}
	catch (std::exception & e)
	{
		QMessageBox msgBox;
		msgBox.setText(QCoreApplication::translate("main", "Exception occurred"));
		msgBox.setInformativeText(QString::fromLatin1(e.what()));
		msgBox.setIcon(QMessageBox::Critical);
		msgBox.exec();
		returnValue = 2;
	}
	catch (...)
	{
		QMessageBox msgBox;
		msgBox.setText(QCoreApplication::translate("main", "Unknown exception occurred"));
		msgBox.setIcon(QMessageBox::Critical);
		msgBox.exec();
		returnValue = 2;
	}

	return returnValue;
}

ext: cpp

max_stars_repo_name: rhiestan/RegardRGBD

max_issues_repo_name: rhiestan/RegardRGBD

max_forks_repo_name: rhiestan/RegardRGBD


text:
//==================================================================================================
/*!
  @file

  @copyright 2015 NumScale SAS
  @copyright 2015 J.T. Lapreste

  Distributed under the Boost Software License, Version 1.0.
  (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
*/
//==================================================================================================
#ifndef BOOST_SIMD_ARCH_COMMON_SCALAR_FUNCTION_INEARBYINT_HPP_INCLUDED
#define BOOST_SIMD_ARCH_COMMON_SCALAR_FUNCTION_INEARBYINT_HPP_INCLUDED

#include <boost/simd/function/fast.hpp>
#include <boost/simd/function/nearbyint.hpp>
#include <boost/simd/function/toint.hpp>
#include <boost/simd/detail/dispatch/function/overload.hpp>
#include <boost/simd/detail/dispatch/meta/as_integer.hpp>
#include <boost/config.hpp>

namespace boost { namespace simd { namespace ext
{
  namespace bd = boost::dispatch;
  BOOST_DISPATCH_OVERLOAD ( inearbyint_
                          , (typename A0)
                          , bd::cpu_
                          , bd::scalar_<bd::integer_<A0> >
                          )
  {
    BOOST_FORCEINLINE A0 operator() ( A0 a0) const BOOST_NOEXCEPT
    {
      return a0;
    }
  };
  BOOST_DISPATCH_OVERLOAD ( inearbyint_
                          , (typename A0)
                          , bd::cpu_
                          , bd::scalar_<bd::floating_<A0> >
                          )
  {
    BOOST_FORCEINLINE bd::as_integer_t<A0> operator() ( A0 a0) const BOOST_NOEXCEPT
    {
      return saturated_(toint)(nearbyint(a0));
    }
  };
  BOOST_DISPATCH_OVERLOAD ( inearbyint_
                          , (typename A0)
                          , bd::cpu_
                          , boost::simd::fast_tag
                          , bd::scalar_<bd::integer_<A0> >
                          )
  {
    BOOST_FORCEINLINE A0 operator() (const fast_tag &,  A0 a0
                                    ) const BOOST_NOEXCEPT
    {
      return a0;
    }
  };
  BOOST_DISPATCH_OVERLOAD ( inearbyint_
                          , (typename A0)
                          , bd::cpu_
                          , boost::simd::fast_tag
                          , bd::scalar_<bd::floating_<A0> >
                          )
  {
    BOOST_FORCEINLINE bd::as_integer_t<A0> operator() (const fast_tag &,  A0 a0
                                                      ) const BOOST_NOEXCEPT
    {
      return toint(nearbyint(a0));
    }
  };
} } }

#endif

ext: hpp

max_stars_repo_name: xmar/pythran

max_issues_repo_name: xmar/pythran

max_forks_repo_name: xmar/pythran


text:
//---------------------------------------------------------------------------//
// Copyright (c) 2013-2014 Kyle Lutz <kyle.r.lutz@gmail.com>
//
// 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
//
// See http://boostorg.github.com/compute for more information.
//---------------------------------------------------------------------------//

#ifndef BOOST_COMPUTE_DETAIL_VENDOR_HPP
#define BOOST_COMPUTE_DETAIL_VENDOR_HPP

#include <boost/compute/device.hpp>
#include <boost/compute/platform.hpp>

namespace boost {
namespace compute {
namespace detail {

// returns true if the device is an nvidia gpu
inline bool is_nvidia_device(const device &device)
{
    std::string nvidia("NVIDIA");
    return device.vendor().compare(0, nvidia.size(), nvidia) == 0;
}

// returns true if the device is an amd cpu or gpu
inline bool is_amd_device(const device &device)
{
    return device.platform().vendor() == "Advanced Micro Devices, Inc.";
}

} // end detail namespace
} // end compute namespace
} // end boost namespace

#endif // BOOST_COMPUTE_DETAIL_VENDOR_HPP


text:
/**
 * Copyright Soramitsu Co., Ltd. All Rights Reserved.
 * SPDX-License-Identifier: Apache-2.0
 */

#ifndef LIBP2P_VISITOR_HPP
#define LIBP2P_VISITOR_HPP

#include <type_traits>  // for std::decay
#include <utility>      // for std::forward

#include <boost/variant/apply_visitor.hpp>  // for boost::apply_visitor

namespace libp2p {

  template <typename... Lambdas>
  struct lambda_visitor;

  template <typename Lambda, typename... Lambdas>
  struct lambda_visitor<Lambda, Lambdas...>
      : public Lambda, public lambda_visitor<Lambdas...> {
    using Lambda::operator();
    using lambda_visitor<Lambdas...>::operator();

    // NOLINTNEXTLINE(google-explicit-constructor)
    lambda_visitor(Lambda lambda, Lambdas... lambdas)
        : Lambda(lambda), lambda_visitor<Lambdas...>(lambdas...) {}
  };

  template <typename Lambda>
  struct lambda_visitor<Lambda> : public Lambda {
    using Lambda::operator();

    // NOLINTNEXTLINE(google-explicit-constructor)
    lambda_visitor(Lambda lambda) : Lambda(lambda) {}
  };

  /**
   * @brief Convenient in-place compile-time visitor creation, from a set of
   * lambdas
   *
   * @code
   * make_visitor([](int a){ return 1; },
   *              [](std::string b) { return 2; });
   * @nocode
   *
   * is essentially the same as
   *
   * @code
   * struct visitor : public boost::static_visitor<int> {
   *   int operator()(int a) { return 1; }
   *   int operator()(std::string b) { return 2; }
   * }
   * @nocode
   *
   * @param lambdas
   * @return visitor
   */
  template <class... Fs>
  constexpr auto make_visitor(Fs &&... fs) {
    using visitor_type = lambda_visitor<std::decay_t<Fs>...>;
    return visitor_type(std::forward<Fs>(fs)...);
  }

  /**
   * @brief Inplace visitor for boost::variant.
   * @code
   *   boost::variant<int, std::string> value = "1234";
   *   ...
   *   visit_in_place(value,
   *                  [](int v) { std::cout << "(int)" << v; },
   *                  [](std::string v) { std::cout << "(string)" << v;}
   *                  );
   * @nocode
   *
   * @param variant
   * @param lambdas
   * @param lambdas
   */
  template <typename TVariant, typename... TVisitors>
  constexpr decltype(auto) visit_in_place(TVariant &&variant,
                                          TVisitors &&... visitors) {
    return boost::apply_visitor(
        make_visitor(std::forward<TVisitors>(visitors)...),
        std::forward<TVariant>(variant));
  }

  /// apply Matcher to optional T
  template <typename T, typename Matcher>
  constexpr decltype(auto) match(T &&t, Matcher &&m) {
    return std::forward<T>(t) ? std::forward<Matcher>(m)(*std::forward<T>(t))
                              : std::forward<Matcher>(m)();
  }

  /// construct visitor from Fs and apply it to optional T
  template <typename T, typename... Fs>
  constexpr decltype(auto) match_in_place(T &&t, Fs &&... fs) {
    return match(std::forward<T>(t), make_visitor(std::forward<Fs>(fs)...));
  }
}  // namespace kagome

#endif  // LIBP2P_VISITOR_HPP


text:
/*

@Copyright Barrett Adair 2015-2017
Distributed under the Boost Software License, Version 1.0.
(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)

*/

#ifndef BOOST_CLBL_TRTS_DETAIL_SET_FUNCTION_QUALIFIERS_HPP
#define BOOST_CLBL_TRTS_DETAIL_SET_FUNCTION_QUALIFIERS_HPP

#include <boost/callable_traits/detail/qualifier_flags.hpp>

#define BOOST_CLBL_TRTS_SET_FUNCTION_QUALIFIERS(QUAL)                          \
  template <typename Return, typename... Args>                                 \
  struct set_function_qualifiers_t<flag_map<int QUAL>::value, false, false,    \
                                   Return, Args...> {                          \
    using type = Return(Args...) QUAL;                                         \
  };                                                                           \
                                                                               \
  template <typename Return, typename... Args>                                 \
  struct set_function_qualifiers_t<flag_map<int QUAL>::value, true, false,     \
                                   Return, Args...> {                          \
    using type =                                                               \
        Return(Args...) QUAL BOOST_CLBL_TRTS_TRANSACTION_SAFE_SPECIFIER;       \
  };                                                                           \
                                                                               \
  template <typename Return, typename... Args>                                 \
  struct set_function_qualifiers_t<flag_map<int QUAL>::value, false, true,     \
                                   Return, Args...> {                          \
    using type = Return(Args...) QUAL BOOST_CLBL_TRTS_NOEXCEPT_SPECIFIER;      \
  };                                                                           \
                                                                               \
  template <typename Return, typename... Args>                                 \
  struct set_function_qualifiers_t<flag_map<int QUAL>::value, true, true,      \
                                   Return, Args...> {                          \
    using type =                                                               \
        Return(Args...) QUAL BOOST_CLBL_TRTS_TRANSACTION_SAFE_SPECIFIER        \
        BOOST_CLBL_TRTS_NOEXCEPT_SPECIFIER;                                    \
  };                                                                           \
                                                                               \
  template <typename Return, typename... Args>                                 \
  struct set_varargs_function_qualifiers_t<flag_map<int QUAL>::value, false,   \
                                           false, Return, Args...> {           \
    using type = Return(Args..., ...) QUAL;                                    \
  };                                                                           \
                                                                               \
  template <typename Return, typename... Args>                                 \
  struct set_varargs_function_qualifiers_t<flag_map<int QUAL>::value, true,    \
                                           false, Return, Args...> {           \
    using type = Return(Args...,                                               \
                        ...) QUAL BOOST_CLBL_TRTS_TRANSACTION_SAFE_SPECIFIER;  \
  };                                                                           \
                                                                               \
  template <typename Return, typename... Args>                                 \
  struct set_varargs_function_qualifiers_t<flag_map<int QUAL>::value, false,   \
                                           true, Return, Args...> {            \
    using type = Return(Args..., ...) QUAL BOOST_CLBL_TRTS_NOEXCEPT_SPECIFIER; \
  };                                                                           \
                                                                               \
  template <typename Return, typename... Args>                                 \
  struct set_varargs_function_qualifiers_t<flag_map<int QUAL>::value, true,    \
                                           true, Return, Args...> {            \
    using type = Return(Args...,                                               \
                        ...) QUAL BOOST_CLBL_TRTS_TRANSACTION_SAFE_SPECIFIER   \
        BOOST_CLBL_TRTS_NOEXCEPT_SPECIFIER;                                    \
  } /**/

namespace boost {
namespace callable_traits {
namespace detail {

template <qualifier_flags Applied, bool IsTransactionSafe, bool IsNoexcept,
          typename Return, typename... Args>
struct set_function_qualifiers_t {
  using type = Return(Args...);
};

template <qualifier_flags Applied, bool IsTransactionSafe, bool IsNoexcept,
          typename Return, typename... Args>
struct set_varargs_function_qualifiers_t {
  using type = Return(Args..., ...);
};

#ifndef BOOST_CLBL_TRTS_DISABLE_ABOMINABLE_FUNCTIONS

BOOST_CLBL_TRTS_SET_FUNCTION_QUALIFIERS(const);
BOOST_CLBL_TRTS_SET_FUNCTION_QUALIFIERS(volatile);
BOOST_CLBL_TRTS_SET_FUNCTION_QUALIFIERS(const volatile);

#ifndef BOOST_CLBL_TRTS_DISABLE_REFERENCE_QUALIFIERS

BOOST_CLBL_TRTS_SET_FUNCTION_QUALIFIERS(&);
BOOST_CLBL_TRTS_SET_FUNCTION_QUALIFIERS(&&);
BOOST_CLBL_TRTS_SET_FUNCTION_QUALIFIERS(const &);
BOOST_CLBL_TRTS_SET_FUNCTION_QUALIFIERS(const &&);
BOOST_CLBL_TRTS_SET_FUNCTION_QUALIFIERS(volatile &);
BOOST_CLBL_TRTS_SET_FUNCTION_QUALIFIERS(volatile &&);
BOOST_CLBL_TRTS_SET_FUNCTION_QUALIFIERS(const volatile &);
BOOST_CLBL_TRTS_SET_FUNCTION_QUALIFIERS(const volatile &&);

#endif // #ifndef BOOST_CLBL_TRTS_DISABLE_REFERENCE_QUALIFIERS
#endif // #ifndef BOOST_CLBL_TRTS_DISABLE_ABOMINABLE_FUNCTIONS

template <qualifier_flags Flags, bool IsTransactionSafe, bool IsNoexcept,
          typename... Ts>
using set_function_qualifiers =
    typename set_function_qualifiers_t<Flags, IsTransactionSafe, IsNoexcept,
                                       Ts...>::type;

template <qualifier_flags Flags, bool IsTransactionSafe, bool IsNoexcept,
          typename... Ts>
using set_varargs_function_qualifiers =
    typename set_varargs_function_qualifiers_t<Flags, IsTransactionSafe,
                                               IsNoexcept, Ts...>::type;

} // namespace detail
} // namespace callable_traits
} // namespace boost

#endif // BOOST_CLBL_TRTS_DETAIL_SET_FUNCTION_QUALIFIERS_HPP

max_stars_repo_name: henrywarhurst/matrix

max_issues_repo_name: henrywarhurst/matrix

max_forks_repo_name: henrywarhurst/matrix


text:
#include "playchain_common.hpp"

#include <playchain/chain/schema/room_object.hpp>
#include <playchain/chain/schema/table_object.hpp>

#include <boost/lambda/lambda.hpp>
#include <boost/multi_index/detail/unbounded.hpp>

#include <playchain/chain/evaluators/db_helpers.hpp>
#include <graphene/chain/hardfork.hpp>

namespace room_rating_tests
{
struct room_rating_fixture : public playchain_common::playchain_fixture
{
    const int64_t registrator_init_balance = 3000 * GRAPHENE_BLOCKCHAIN_PRECISION;

    DECLARE_ACTOR(richregistrator)
    DECLARE_ACTOR(temp)

    room_rating_fixture()
    {
        actor(richregistrator).supply(asset(registrator_init_balance));
        actor(temp).supply(asset(player_init_balance));

        init_fees();

        generate_blocks(db.get_dynamic_global_properties().next_maintenance_time);
    }

    table_id_type create_new_table(const Actor& owner, const room_id_type &room, const amount_type required_witnesses = 0u, const std::string &metadata = {})
    {
        table_id_type table = playchain_common::playchain_fixture::create_new_table(owner, room, required_witnesses, metadata);
        table_alive(richregistrator, table);
        return table;
    }
};

BOOST_FIXTURE_TEST_SUITE(room_rating_tests, room_rating_fixture)

PLAYCHAIN_TEST_CASE(check_rating_changes_only_in_maintance)
{
    generate_blocks(HARDFORK_PLAYCHAIN_5_TIME);

    const std::string protocol_version = "1.0.0+20190223";
    const std::string meta = "Game";

    room_id_type room = create_new_room(richregistrator, "room", protocol_version);
    table_id_type table = create_new_table(richregistrator, room, 0u, meta);

    Actor player1 = create_new_player(richregistrator, "player1", asset(player_init_balance));

    auto initial_room_rating = room(db).rating;

    generate_block();

    auto stake = asset(player_init_balance / 3);

    BOOST_REQUIRE_NO_THROW(buy_in_reserve(player1, get_next_uid(actor(player1)), stake, meta, protocol_version));

    generate_block();

    BOOST_REQUIRE(!table(db).pending_proposals.empty());
    BOOST_REQUIRE_NO_THROW(buy_in_reserving_resolve(richregistrator, table, table(db).pending_proposals.begin()->second));

    generate_blocks(db.get_dynamic_global_properties().next_maintenance_time - GRAPHENE_DEFAULT_BLOCK_INTERVAL);

    BOOST_CHECK_EQUAL(initial_room_rating, room(db).rating);

    generate_blocks(db.get_dynamic_global_properties().next_maintenance_time);

    BOOST_CHECK_NE(initial_room_rating, room(db).rating);
}

PLAYCHAIN_TEST_CASE(check_failed_resolve_results_in_rating_degrodation)
{
    generate_blocks(HARDFORK_PLAYCHAIN_5_TIME);

    const std::string protocol_version = "1.0.0+20190223";

    const std::string meta = "Game";

    room_id_type room = create_new_room(richregistrator, "room", protocol_version);
    room_id_type room2 = create_new_room(richregistrator, "room2", protocol_version);
    table_id_type table = create_new_table(richregistrator, room, 0u, meta);
    table_id_type table2 = create_new_table(richregistrator, room2, 0u, meta);

    Actor player1 = create_new_player(richregistrator, "player1", asset(player_init_balance));
    Actor player2 = create_new_player(richregistrator, "player2", asset(player_init_balance));
    Actor player3 = create_new_player(richregistrator, "player3", asset(player_init_balance));
    Actor player4 = create_new_player(richregistrator, "player4", asset(player_init_balance));

    auto stake = asset(player_init_balance / 3);

    generate_block();

    BOOST_TEST_MESSAGE("\nSTART BUYIN_RESERVE");

    // update parameter for test needs
    db.modify(get_playchain_properties(db), [&](playchain_property_object& p) {
        p.parameters.maximum_desired_number_of_players_for_tables_allocation = 2;
    });
    BOOST_REQUIRE_EQUAL(get_playchain_parameters(db).maximum_desired_number_of_players_for_tables_allocation, 2u);

    BOOST_REQUIRE_NO_THROW(buy_in_reserve(player1, get_next_uid(actor(player1)), stake, meta, protocol_version));
    BOOST_REQUIRE_NO_THROW(buy_in_reserve(player2, get_next_uid(actor(player2)), stake, meta, protocol_version));
    BOOST_REQUIRE_NO_THROW(buy_in_reserve(player3, get_next_uid(actor(player3)), stake, meta, protocol_version));
    BOOST_REQUIRE_NO_THROW(buy_in_reserve(player4, get_next_uid(actor(player4)), stake, meta, protocol_version));

    generate_block();

    BOOST_TEST_MESSAGE("\nSTART BUYIN_RESOLVE");

    BOOST_REQUIRE_EQUAL(table(db).get_pending_proposals(), 2u);
    BOOST_REQUIRE_EQUAL(table2(db).get_pending_proposals(), 2u);
    BOOST_REQUIRE_NO_THROW(buy_in_reserving_resolve(richregistrator, table, table(db).pending_proposals.begin()->second));
    BOOST_REQUIRE_NO_THROW(buy_in_reserving_resolve(richregistrator, table, table(db).pending_proposals.begin()->second));
    BOOST_REQUIRE_NO_THROW(buy_in_reserving_resolve(richregistrator, table2, table2(db).pending_proposals.begin()->second));

    BOOST_TEST_MESSAGE("\nGENERATE_UNTIL_EXPIRATION");
    generate_blocks(db.get_dynamic_global_properties().time + fc::seconds(get_playchain_parameters(db).buy_in_expiration_seconds));

    BOOST_TEST_MESSAGE("\nGENERATE MAINTANCE");
    generate_blocks(db.get_dynamic_global_properties().next_maintenance_time);

    BOOST_REQUIRE_EQUAL(table(db).get_pending_proposals(), 0u);
    BOOST_REQUIRE_EQUAL(table2(db).get_pending_proposals(), 0u);

    auto room_exelent_rating = room(db).rating;
    auto room_1fail_rating = room2(db).rating;

    BOOST_CHECK_LT(room_1fail_rating, room_exelent_rating);
}

PLAYCHAIN_TEST_CASE(check_more_buyins_give_higher_rating)
{
    generate_blocks(HARDFORK_PLAYCHAIN_5_TIME);

    const std::string protocol_version = "1.0.0+20190223";

    const std::string meta = "Game";

    room_id_type room = create_new_room(richregistrator, "room", protocol_version);
    room_id_type room2 = create_new_room(richregistrator, "room2", protocol_version);
    table_id_type table = create_new_table(richregistrator, room, 0u, meta);
    table_id_type table2 = create_new_table(richregistrator, room2, 0u, meta);

    Actor player1 = create_new_player(richregistrator, "player1", asset(player_init_balance));
    Actor player2 = create_new_player(richregistrator, "player2", asset(player_init_balance));
    Actor player3 = create_new_player(richregistrator, "player3", asset(player_init_balance));

    auto stake = asset(player_init_balance / 3);

    generate_block();

    BOOST_TEST_MESSAGE("\nSTART BUYIN_RESERVE");

    // update parameter for test needs
    db.modify(get_playchain_properties(db), [&](playchain_property_object& p) {
        p.parameters.maximum_desired_number_of_players_for_tables_allocation = 2;
    });
    BOOST_REQUIRE_EQUAL(get_playchain_parameters(db).maximum_desired_number_of_players_for_tables_allocation, 2u);

    BOOST_REQUIRE_NO_THROW(buy_in_reserve(player1, get_next_uid(actor(player1)), stake, meta, protocol_version));
    BOOST_REQUIRE_NO_THROW(buy_in_reserve(player2, get_next_uid(actor(player2)), stake, meta, protocol_version));
    BOOST_REQUIRE_NO_THROW(buy_in_reserve(player3, get_next_uid(actor(player3)), stake, meta, protocol_version));

    generate_block();

    BOOST_TEST_MESSAGE("\nSTART BUYIN_RESOLVE");

    BOOST_REQUIRE_EQUAL(table(db).get_pending_proposals(), 2u);
    BOOST_REQUIRE_EQUAL(table2(db).get_pending_proposals(), 1u);
    BOOST_REQUIRE_NO_THROW(buy_in_reserving_resolve(richregistrator, table, table(db).pending_proposals.begin()->second));
    BOOST_REQUIRE_NO_THROW(buy_in_reserving_resolve(richregistrator, table, table(db).pending_proposals.begin()->second));
    BOOST_REQUIRE_NO_THROW(buy_in_reserving_resolve(richregistrator, table2, table2(db).pending_proposals.begin()->second));

    generate_block();

    BOOST_TEST_MESSAGE("\nGENERATE MAINTANCE");
    generate_blocks(db.get_dynamic_global_properties().next_maintenance_time);

    BOOST_REQUIRE_EQUAL(table(db).get_pending_proposals(), 0u);
    BOOST_REQUIRE_EQUAL(table2(db).get_pending_proposals(), 0u);

    BOOST_CHECK_LT(room2(db).rating, room(db).rating);
}

PLAYCHAIN_TEST_CASE(check_canceled_buyin_does_not_influence_rating)
{
    generate_blocks(HARDFORK_PLAYCHAIN_5_TIME);

    const std::string protocol_version = "1.0.0+20190223";

    const std::string meta = "Game";

    room_id_type room = create_new_room(richregistrator, "room", protocol_version);
    room_id_type room2 = create_new_room(richregistrator, "room2", protocol_version);
    table_id_type table = create_new_table(richregistrator, room, 0u, meta);
    table_id_type table2 = create_new_table(richregistrator, room2, 0u, meta);

    Actor player1 = create_new_player(richregistrator, "player1", asset(player_init_balance));
    Actor player2 = create_new_player(richregistrator, "player2", asset(player_init_balance));
    Actor player3 = create_new_player(richregistrator, "player3", asset(player_init_balance));

    auto stake = asset(player_init_balance / 3);

    generate_block();

    BOOST_TEST_MESSAGE("\nSTART BUYIN_RESERVE");

    // update parameter for test needs
    db.modify(get_playchain_properties(db), [&](playchain_property_object& p) {
        p.parameters.maximum_desired_number_of_players_for_tables_allocation = 2;
    });
    BOOST_REQUIRE_EQUAL(get_playchain_parameters(db).maximum_desired_number_of_players_for_tables_allocation, 2u);

    string player2_uid = get_next_uid(actor(player2));

    BOOST_REQUIRE_NO_THROW(buy_in_reserve(player1, get_next_uid(actor(player1)), stake, meta, protocol_version));
    BOOST_REQUIRE_NO_THROW(buy_in_reserve(player2, player2_uid, stake, meta, protocol_version));
    BOOST_REQUIRE_NO_THROW(buy_in_reserve(player3, get_next_uid(actor(player3)), stake, meta, protocol_version));

    generate_block();

    BOOST_TEST_MESSAGE("\nSTART BUYIN_RESOLVE");

    BOOST_REQUIRE_EQUAL(table(db).get_pending_proposals(), 2u);
    BOOST_REQUIRE_EQUAL(table2(db).get_pending_proposals(), 1u);
    BOOST_REQUIRE_NO_THROW(buy_in_reserving_resolve(richregistrator, table, table(db).pending_proposals.begin()->second));
    BOOST_REQUIRE_NO_THROW(buy_in_reserving_resolve(richregistrator, table2, table2(db).pending_proposals.begin()->second));
    BOOST_REQUIRE_NO_THROW(buy_in_reserving_cancel(player2, player2_uid));

    generate_block();

    BOOST_TEST_MESSAGE("\nGENERATE MAINTANCE");
    generate_blocks(db.get_dynamic_global_properties().next_maintenance_time);

    BOOST_REQUIRE_EQUAL(table(db).get_pending_proposals(), 0u);
    BOOST_REQUIRE_EQUAL(table2(db).get_pending_proposals(), 0u);

    auto room_exelent_rating = room(db).rating;
    auto room_1fail_rating = room2(db).rating;

    BOOST_TEST_MESSAGE("\nroom_50percent_rating == " << room_1fail_rating << ", room_100percent_rating == " << room_exelent_rating);

    BOOST_CHECK_EQUAL(room(db).rating, room2(db).rating);
}

PLAYCHAIN_TEST_CASE(check_before_fade_start_buyins_give_the_same_contribution_to_rating)
{
    generate_blocks(HARDFORK_PLAYCHAIN_5_TIME);

    const std::string protocol_version = "1.0.0+20190223";

    const std::string meta = "Game";

    room_id_type room = create_new_room(richregistrator, "room", protocol_version);
    room_id_type room2 = create_new_room(richregistrator, "room2", protocol_version);
    table_id_type table = create_new_table(richregistrator, room, 0u, meta);
    table_id_type table2 = create_new_table(richregistrator, room2, 0u, meta);

    Actor player1 = create_new_player(richregistrator, "player1", asset(player_init_balance));
    Actor player2 = create_new_player(richregistrator, "player2", asset(player_init_balance));

    auto stake = asset(player_init_balance / 3);

    generate_blocks(db.get_dynamic_global_properties().next_maintenance_time - fc::minutes(TIME_FACTOR_FADE_START));

    // update parameter for test needs
    db.modify(get_playchain_properties(db), [&](playchain_property_object& p) {
        p.parameters.maximum_desired_number_of_players_for_tables_allocation = 1;
        p.parameters.buy_in_expiration_seconds = (uint32_t)fc::minutes(TIME_FACTOR_FADE_START).to_seconds();
    });
    BOOST_REQUIRE_EQUAL(get_playchain_parameters(db).maximum_desired_number_of_players_for_tables_allocation, 1u);

    BOOST_TEST_MESSAGE("\nSTART BUYIN ON TABLE1");
    table_alive(richregistrator, table);
    BOOST_REQUIRE_NO_THROW(buy_in_reserve(player1, get_next_uid(actor(player1)), stake, meta, protocol_version));
    generate_block();
    BOOST_REQUIRE_EQUAL(table(db).get_pending_proposals(), 1u);
    BOOST_REQUIRE_NO_THROW(buy_in_reserving_resolve(richregistrator, table, table(db).pending_proposals.begin()->second));
    generate_block();

    //move to begin of no-fade period
    generate_blocks(db.get_dynamic_global_properties().time + fc::minutes(TIME_FACTOR_FADE_START-1));

    BOOST_TEST_MESSAGE("\nSTART BUYIN ON TABLE2");
    table_alive(richregistrator, table2);
    BOOST_REQUIRE_NO_THROW(buy_in_reserve(player2, get_next_uid(actor(player2)), stake, meta, protocol_version));
    generate_block();
    BOOST_TEST_MESSAGE("\n" << table(db).get_pending_proposals() << "  " << table2(db).get_pending_proposals());
    BOOST_REQUIRE_EQUAL(table2(db).get_pending_proposals(), 1u);
    BOOST_REQUIRE_NO_THROW(buy_in_reserving_resolve(richregistrator, table2, table2(db).pending_proposals.begin()->second));
    generate_block();

    BOOST_TEST_MESSAGE("\nGENERATE MAINTANCE");
    generate_blocks(db.get_dynamic_global_properties().next_maintenance_time);

    BOOST_REQUIRE_EQUAL(table(db).get_pending_proposals(), 0u);
    BOOST_REQUIRE_EQUAL(table2(db).get_pending_proposals(), 0u);

    auto room1_exelent_rating = room(db).rating;
    auto room2_exelent_rating = room2(db).rating;

    BOOST_TEST_MESSAGE("\nroom1_exelent_rating == " << room1_exelent_rating << ", room2_exelent_rating == " << room2_exelent_rating);

    BOOST_CHECK_EQUAL(room(db).rating, room2(db).rating);
}

PLAYCHAIN_TEST_CASE(check_notresolved_buyins_are_not_used_in_rating_count)
{
    generate_blocks(HARDFORK_PLAYCHAIN_5_TIME);

    const std::string protocol_version = "1.0.0+20190223";

    const std::string meta = "Game";

    room_id_type room = create_new_room(richregistrator, "room", protocol_version);
    room_id_type room2 = create_new_room(richregistrator, "room2", protocol_version);
    table_id_type table = create_new_table(richregistrator, room, 0u, meta);
    table_id_type table2 = create_new_table(richregistrator, room2, 0u, meta);

    Actor player1 = create_new_player(richregistrator, "player1", asset(player_init_balance));
    Actor player2 = create_new_player(richregistrator, "player2", asset(player_init_balance));
    Actor player3 = create_new_player(richregistrator, "player3", asset(player_init_balance));

    auto stake = asset(player_init_balance / 3);

    const auto delta_until_maintance = 2;

    generate_block();
    generate_blocks(db.get_dynamic_global_properties().next_maintenance_time - fc::minutes(delta_until_maintance));

    BOOST_TEST_MESSAGE("\nSTART BUYIN_RESERVE");

    // update parameter for test needs
    db.modify(get_playchain_properties(db), [&](playchain_property_object& p) {
        p.parameters.maximum_desired_number_of_players_for_tables_allocation = 2;
        p.parameters.pending_buyin_proposal_lifetime_limit_in_seconds = fc::minutes(delta_until_maintance + 1).to_seconds();
    });
    BOOST_REQUIRE_EQUAL(get_playchain_parameters(db).maximum_desired_number_of_players_for_tables_allocation, 2u);

    table_alive(richregistrator, table);
    table_alive(richregistrator, table2);

    BOOST_REQUIRE_NO_THROW(buy_in_reserve(player1, get_next_uid(actor(player1)), stake, meta, protocol_version));
    BOOST_REQUIRE_NO_THROW(buy_in_reserve(player2, get_next_uid(actor(player2)), stake, meta, protocol_version));
    BOOST_REQUIRE_NO_THROW(buy_in_reserve(player3, get_next_uid(actor(player3)), stake, meta, protocol_version));

    generate_block();

    BOOST_TEST_MESSAGE("\nSTART BUYIN_RESOLVE");

    BOOST_REQUIRE_EQUAL(table(db).get_pending_proposals(), 2u);
    BOOST_REQUIRE_EQUAL(table2(db).get_pending_proposals(), 1u);
    BOOST_REQUIRE_NO_THROW(buy_in_reserving_resolve(richregistrator, table, table(db).pending_proposals.begin()->second));
    BOOST_REQUIRE_NO_THROW(buy_in_reserving_resolve(richregistrator, table2, table2(db).pending_proposals.begin()->second));

    generate_block();

    BOOST_TEST_MESSAGE("\nGENERATE MAINTANCE");
    generate_blocks(db.get_dynamic_global_properties().next_maintenance_time);

    BOOST_REQUIRE_EQUAL(table(db).get_pending_proposals(), 1u);
    BOOST_REQUIRE_EQUAL(table2(db).get_pending_proposals(), 0u);

    BOOST_CHECK_EQUAL(room2(db).rating, room(db).rating);
}

namespace
{
    template <class T>
    T adjust_precision(const T& val)
    {
        return ROOM_RATING_PRECISION * val;
    }

    uint64_t K_factor(uint64_t x)
    {
        if (x <= TIME_FACTOR_FADE_START)
        {
            return adjust_precision(x);
        }
        else
        {
            return adjust_precision(TIME_FACTOR_C1 * std::exp(TIME_FACTOR_C2 * x) + TIME_FACTOR_C3);
        }
    }

    uint64_t f_N(uint64_t N)
    {
        if (N <= QUANTITY_FACTOR_FADE_START)
        {
            return adjust_precision(QUANTITY_FACTOR_C1 + N * QUANTITY_FACTOR_C2);
        }
        else
        {
            return adjust_precision(std::log(N) / QUANTITY_FACTOR_C3 + QUANTITY_FACTOR_C4);
        }
    }

    uint64_t stat_correction()
    {
        return adjust_precision(STAT_CORRECTION_M);
    }
}

PLAYCHAIN_TEST_CASE(check_calculation_formula)
{
    generate_blocks(HARDFORK_PLAYCHAIN_5_TIME);

    const std::string protocol_version = "1.0.0+20190223";

    const std::string meta = "Game";

    room_id_type room = create_new_room(richregistrator, "room", protocol_version);
    room_id_type room2 = create_new_room(richregistrator, "room2", protocol_version);
    table_id_type table = create_new_table(richregistrator, room, 0u, meta);
    table_id_type table2 = create_new_table(richregistrator, room2, 0u, meta);

    Actor player1 = create_new_player(richregistrator, "player1", asset(player_init_balance));
    Actor player2 = create_new_player(richregistrator, "player2", asset(player_init_balance));
    Actor player3 = create_new_player(richregistrator, "player3", asset(player_init_balance));
    Actor player4 = create_new_player(richregistrator, "player4", asset(player_init_balance));

    auto stake = asset(player_init_balance / 3);

    generate_block();

    auto diff_time1 = db.get_dynamic_global_properties().next_maintenance_time.sec_since_epoch() - db.get_dynamic_global_properties().time.sec_since_epoch();
    auto diff_time2 = diff_time1/2;

    BOOST_TEST_MESSAGE("\nSTART BUYIN ON TABLE1 at time T1");

    BOOST_REQUIRE_NO_THROW(buy_in_reserve(player1, get_next_uid(actor(player1)), stake, meta, protocol_version));
    BOOST_REQUIRE_NO_THROW(buy_in_reserve(player2, get_next_uid(actor(player2)), stake, meta, protocol_version));
    generate_block();
    BOOST_REQUIRE_EQUAL(table(db).get_pending_proposals(), 2u);
    BOOST_REQUIRE_NO_THROW(buy_in_reserving_resolve(richregistrator, table, table(db).pending_proposals.begin()->second));
    generate_block();

    generate_blocks(db.get_dynamic_global_properties().time + diff_time2);

    // update parameter for test needs
    db.modify(get_playchain_properties(db), [&](playchain_property_object& p) {
        p.parameters.maximum_desired_number_of_players_for_tables_allocation = 2;
    });
    BOOST_REQUIRE_EQUAL(get_playchain_parameters(db).maximum_desired_number_of_players_for_tables_allocation, 2u);

    table_alive(richregistrator, table);
    table_alive(richregistrator, table2);

    BOOST_TEST_MESSAGE("\nSTART BUYIN ON TABLE1 at time T2");
    BOOST_REQUIRE_NO_THROW(buy_in_reserve(player1, get_next_uid(actor(player1)), stake, meta, protocol_version));
    BOOST_REQUIRE_NO_THROW(buy_in_reserve(player2, get_next_uid(actor(player2)), stake, meta, protocol_version));
    BOOST_REQUIRE_NO_THROW(buy_in_reserve(player3, get_next_uid(actor(player3)), stake, meta, protocol_version));
    BOOST_REQUIRE_NO_THROW(buy_in_reserve(player4, get_next_uid(actor(player4)), stake, meta, protocol_version));
    generate_block();
    BOOST_REQUIRE_EQUAL(table(db).get_pending_proposals(), 2u);
    BOOST_REQUIRE_EQUAL(table2(db).get_pending_proposals(), 2u);
    BOOST_REQUIRE_NO_THROW(buy_in_reserving_resolve(richregistrator, table, table(db).pending_proposals.begin()->second));
    BOOST_REQUIRE_NO_THROW(buy_in_reserving_resolve(richregistrator, table2, table2(db).pending_proposals.begin()->second));
    generate_block();

    BOOST_TEST_MESSAGE("\nGENERATE MAINTANCE");
    generate_blocks(db.get_dynamic_global_properties().next_maintenance_time - GRAPHENE_DEFAULT_BLOCK_INTERVAL);
    generate_block();

    BOOST_REQUIRE_EQUAL(table(db).get_pending_proposals(), 0u);

    auto room1_rating_in_blockchain = room(db).rating;
    auto room2_rating_in_blockchain = room2(db).rating;

    //////////////////////////////////////////////////////////////////////////
    //      calculate room rating
    //////////////////////////////////////////////////////////////////////////

    auto room1_time_coef = K_factor(diff_time1/60) + K_factor(diff_time1 / 60) + K_factor(diff_time2 / 60) + K_factor(diff_time2 / 60);
    auto room1_weight_with_time_coef = 1*K_factor(diff_time1 / 60) + 0*K_factor(diff_time1 / 60) + 1*K_factor(diff_time2 / 60) + 0*K_factor(diff_time2 / 60);

    auto room2_time_coef = K_factor(diff_time2 / 60) + K_factor(diff_time2 / 60);
    auto room2_weight_with_time_coef = 1 * K_factor(diff_time2 / 60) + 0 * K_factor(diff_time2 / 60);

    const auto M = stat_correction();

    auto time_coef = room1_time_coef + room2_time_coef;
    auto weight_with_time_coef = room1_weight_with_time_coef + room2_weight_with_time_coef;

    BOOST_TEST_MESSAGE("\n"<< weight_with_time_coef<<" "<< time_coef<< " " << M << " ");

    const auto room1_calculated_rating = (room1_weight_with_time_coef + weight_with_time_coef * M/ time_coef) * 25 * f_N(4) / (room1_time_coef + M);
    const auto room2_calculated_rating = (room2_weight_with_time_coef + weight_with_time_coef * M / time_coef) * 25 * f_N(2) / (room2_time_coef + M);

    BOOST_CHECK_EQUAL(room1_rating_in_blockchain, room1_calculated_rating);
    BOOST_CHECK_EQUAL(room2_rating_in_blockchain, room2_calculated_rating);
}

PLAYCHAIN_TEST_CASE(check_initial_room_rating_equals_0_before_playchain_5hf)
{
    const std::string protocol_version = "1.0.0+20190223";

    room_id_type room = create_new_room(richregistrator, "room", protocol_version);

    BOOST_CHECK_EQUAL(0, room(db).rating);
}

PLAYCHAIN_TEST_CASE(check_initial_room_rating_equals_avarage_rating_after_playchain_5hf)
{
    generate_blocks(HARDFORK_PLAYCHAIN_5_TIME);

    const std::string protocol_version = "1.0.0+20190223";
    const std::string meta = "Game";

    room_id_type room = create_new_room(richregistrator, "room", protocol_version);
    BOOST_CHECK_EQUAL(0, room(db).rating);

    table_id_type table = create_new_table(richregistrator, room, 0u, meta);
    Actor player1 = create_new_player(richregistrator, "player1", asset(player_init_balance));

    auto stake = asset(player_init_balance / 3);
    BOOST_REQUIRE_NO_THROW(buy_in_reserve(player1, get_next_uid(actor(player1)), stake, meta, protocol_version));
    generate_block();
    BOOST_REQUIRE(!table(db).pending_proposals.empty());
    BOOST_REQUIRE_NO_THROW(buy_in_reserving_resolve(richregistrator, table, table(db).pending_proposals.begin()->second));
    generate_block();

    generate_blocks(db.get_dynamic_global_properties().next_maintenance_time);

    BOOST_REQUIRE_NE(0, room(db).rating);
    BOOST_REQUIRE_NE(0, db.get_dynamic_global_properties().average_room_rating);
    BOOST_REQUIRE_EQUAL(room(db).rating, db.get_dynamic_global_properties().average_room_rating);

    room_id_type room2 = create_new_room(richregistrator, "room2", protocol_version);
    BOOST_REQUIRE_EQUAL(room2(db).rating, db.get_dynamic_global_properties().average_room_rating);
}

PLAYCHAIN_TEST_CASE(check_room_rake_changing)
{
    generate_blocks(HARDFORK_PLAYCHAIN_2_TIME);

    const std::string meta = "Game";

    room_id_type room1 = create_new_room(richregistrator, "room1");
    table_id_type table1_1 = create_new_table(richregistrator, room1, 0u, meta);
    table_id_type table1_2 = create_new_table(richregistrator, room1, 0u, meta);

    room_id_type room2 = create_new_room(richregistrator, "room2");
    table_id_type table2_1 = create_new_table(richregistrator, room2, 0u, meta);
    table_id_type table2_2 = create_new_table(richregistrator, room2, 0u, meta);

    Actor player1 = create_new_player(richregistrator, "p1", asset(player_init_balance));
    Actor player2 = create_new_player(richregistrator, "p2", asset(player_init_balance));
    Actor player3 = create_new_player(richregistrator, "p3", asset(player_init_balance));

    auto stake = asset(player_init_balance / 2);

    // update parameter for test needs
    db.modify(room1(db), [&](room_object& r) {
        r.rating = 10;
    });
    BOOST_REQUIRE_EQUAL(room1(db).rating, 10);
    BOOST_REQUIRE_EQUAL(room2(db).rating, 0);

    BOOST_REQUIRE_NO_THROW(table_alive(richregistrator, table1_1));
    BOOST_REQUIRE_NO_THROW(table_alive(richregistrator, table1_2));
    BOOST_REQUIRE_NO_THROW(table_alive(richregistrator, table2_1));
    BOOST_REQUIRE_NO_THROW(table_alive(richregistrator, table2_2));

    BOOST_REQUIRE_NO_THROW(buy_in_reserve(player1, get_next_uid(actor(player1)), stake, meta));
    BOOST_REQUIRE_NO_THROW(buy_in_reserve(player2, get_next_uid(actor(player2)), stake, meta));
    BOOST_REQUIRE_NO_THROW(buy_in_reserve(player3, get_next_uid(actor(player3)), stake, meta));

    generate_block();

    BOOST_CHECK_EQUAL(table1_1(db).get_pending_proposals(), 3u);
    BOOST_CHECK_EQUAL(table1_2(db).get_pending_proposals(), 0u);
    BOOST_CHECK_EQUAL(table2_1(db).get_pending_proposals(), 0u);
    BOOST_CHECK_EQUAL(table2_2(db).get_pending_proposals(), 0u);

    generate_blocks(db.get_dynamic_global_properties().time + get_playchain_properties(db).parameters.pending_buyin_proposal_lifetime_limit_in_seconds);

    BOOST_REQUIRE_EQUAL(table1_1(db).get_pending_proposals(), 0u);
    BOOST_REQUIRE_EQUAL(table1_2(db).get_pending_proposals(), 0u);
    BOOST_REQUIRE_EQUAL(table2_1(db).get_pending_proposals(), 0u);
    BOOST_REQUIRE_EQUAL(table2_2(db).get_pending_proposals(), 0u);

    // update parameter for test needs
    db.modify(room1(db), [&](room_object& r) {
        r.rating = 10;
    });
    db.modify(room2(db), [&](room_object& r) {
        r.rating = 20;
    });
    BOOST_REQUIRE_EQUAL(room1(db).rating, 10);
    BOOST_REQUIRE_EQUAL(room2(db).rating, 20);

    BOOST_REQUIRE_NO_THROW(table_alive(richregistrator, table1_1));
    BOOST_REQUIRE_NO_THROW(table_alive(richregistrator, table1_2));
    BOOST_REQUIRE_NO_THROW(table_alive(richregistrator, table2_1));
    BOOST_REQUIRE_NO_THROW(table_alive(richregistrator, table2_2));

    BOOST_REQUIRE_NO_THROW(buy_in_reserve(player1, get_next_uid(actor(player1)), stake, meta));
    BOOST_REQUIRE_NO_THROW(buy_in_reserve(player2, get_next_uid(actor(player2)), stake, meta));
    BOOST_REQUIRE_NO_THROW(buy_in_reserve(player3, get_next_uid(actor(player3)), stake, meta));

    generate_block();

    BOOST_CHECK_EQUAL(table1_1(db).get_pending_proposals(), 0u);
    BOOST_CHECK_EQUAL(table1_2(db).get_pending_proposals(), 0u);
    BOOST_CHECK_EQUAL(table2_1(db).get_pending_proposals(), 3u);
    BOOST_CHECK_EQUAL(table2_2(db).get_pending_proposals(), 0u);
}

BOOST_AUTO_TEST_SUITE_END()
}

max_stars_repo_name: totalgames/playchain-core

max_issues_repo_name: totalgames/playchain-core

max_forks_repo_name: totalgames/playchain-core


text:
#ifndef WEBSERVER_EXCEPTIONS_HPP
#define WEBSERVER_EXCEPTIONS_HPP

#include <iostream>
#include <boost/asio.hpp>

namespace webserver {

void output_exception(std::exception &e) {
    std::cout << "Exception: " << e.what() << "\n";
}

void output_error(const boost::system::error_code &error) {
    std::cout << "Error: " << error.message() << "\n";
}

void output_error(std::string error_message) {
	std::cout << error_message << "\n";
}

void check_error_code(const boost::system::error_code &error) {
    if (error) {
        output_error(error);
        return;
    }
}

} // namespace webserver

#endif //WEBSERVER_EXCEPTIONS_HPP