github.com/igggame/nebulas-go@v2.1.0+incompatible/nbre/3rd_party/fflib/include/ff/functionflow/para/para.h (about)

     1  /***********************************************
     2    The MIT License (MIT)
     3  
     4    Copyright (c) 2012 Athrun Arthur <athrunarthur@gmail.com>
     5  
     6    Permission is hereby granted, free of charge, to any person obtaining a copy
     7    of this software and associated documentation files (the "Software"), to deal
     8    in the Software without restriction, including without limitation the rights
     9    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    10    copies of the Software, and to permit persons to whom the Software is
    11    furnished to do so, subject to the following conditions:
    12  
    13    The above copyright notice and this permission notice shall be included in
    14    all copies or substantial portions of the Software.
    15  
    16    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    17    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    18    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    19    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    20    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    21    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
    22    THE SOFTWARE.
    23   *************************************************/
    24  #pragma once
    25  #include "ff/functionflow/common/common.h"
    26  #include "ff/functionflow/para/bin_wait_func_deducer.h"
    27  #include "ff/functionflow/para/exception.h"
    28  #include "ff/functionflow/para/is_wait_compatible_with_then.h"
    29  #include "ff/functionflow/para/para_helper.h"
    30  #include "ff/functionflow/para/para_impl.h"
    31  #include "ff/functionflow/para/para_wait_traits.h"
    32  #include "ff/functionflow/runtime/rtcmn.h"
    33  #include "ff/util/function_traits.h"
    34  
    35  namespace ff {
    36  
    37  using namespace ff::util;
    38  namespace internal {
    39  template <typename DT, typename RT>
    40  class para_common {
    41   public:
    42    typedef RT ret_type;
    43  
    44   public:
    45  #include "ff/functionflow/para/para_accepted_wait.h"
    46     para_common() : m_pImpl(nullptr){};
    47     ~para_common() {}
    48     template <class WT>
    49     auto operator[](WT &&cond) -> typename std::enable_if<
    50         is_para_or_wait<typename std::remove_reference<WT>::type>::value,
    51         para_accepted_wait<DT, WT>>::type {
    52       if (cond.get_state() == exe_state::exe_empty)
    53         throw empty_para_exception();
    54       return para_accepted_wait<DT, WT>(*(static_cast<DT *>(this)),
    55                                         std::forward<WT>(cond));
    56     }
    57     template <class WT>
    58     auto operator[](WT &&cond) -> typename std::enable_if<
    59         !is_para_or_wait<typename std::remove_reference<WT>::type>::value,
    60         para_accepted_wait<DT, para<void>>>::type {
    61       static_assert(Please_Check_The_Assert_Msg<WT>::value,
    62                     FF_EM_WRONG_USE_SQPAREN);
    63     }
    64     template <class F> auto exe(F &&f) -> para_accepted_call<DT, ret_type> {
    65       if (m_pImpl)
    66         throw used_para_exception();
    67       auto pp = make_para_impl<ret_type>(std::forward<F>(f));
    68       m_pImpl = std::dynamic_pointer_cast<para_impl_base<ret_type>>(pp);
    69       schedule(m_pImpl);
    70       return para_accepted_call<DT, ret_type>(*(static_cast<DT *>(this)));
    71     }
    72     template <class F>
    73     auto operator()(F &&f) -> typename std::enable_if<
    74         std::is_same<typename ::ff::util::function_res_traits<F>::ret_type,
    75                      ret_type>::value,
    76         para_accepted_call<DT, ret_type>>::type {
    77       return exe(std::forward<F>(f));
    78     }
    79  
    80     template <class F>
    81     auto operator()(F &&f) -> typename std::enable_if<
    82         !std::is_same<typename ::ff::util::function_res_traits<F>::ret_type,
    83                       ret_type>::value,
    84         para_accepted_call<DT, ret_type>>::type {
    85       static_assert(Please_Check_The_Assert_Msg<F>::value,
    86                     FF_EM_CALL_WITH_TYPE_MISMATCH);
    87     }
    88     exe_state get_state() {
    89       if (m_pImpl)
    90         return m_pImpl->get_state();
    91       return exe_state::exe_empty;
    92     }
    93     bool check_if_over() {
    94       if (m_pImpl)
    95         return m_pImpl->check_if_over();
    96       return false;
    97     }
    98  
    99     ::ff::internal::para_impl_base_ptr<ret_type> get_internal_impl() {
   100       return m_pImpl;
   101     }
   102  
   103     template <class F> void then(const F &) {
   104       static_assert(Please_Check_The_Assert_Msg<F>::value,
   105                     FF_EM_CALL_THEN_WITHOUT_CALL_PAREN);
   106     }
   107  
   108   protected:
   109     ::ff::internal::para_impl_base_ptr<ret_type> m_pImpl;
   110  };  // end class para_common
   111  
   112  }  // end namespace internal
   113  
   114  template <typename RT = void>
   115  class para : public ::ff::internal::para_common<para<RT>, RT> {
   116  public:
   117    typedef RT ret_type;
   118    auto get() -> typename std::enable_if<!std::is_void<RT>::value, RT>::type & {
   119      return ::ff::internal::para_common<para<RT>, RT>::m_pImpl->get();
   120    }
   121    template <class FT>
   122    auto internal_then(FT &&f) -> typename std::enable_if<
   123        std::is_void<typename function_res_traits<FT>::ret_type>::value &&
   124            is_function_with_arg_type<FT, ret_type>::value,
   125        void>::type {
   126      f(m_pImpl->get());
   127    }
   128  
   129    template <class FT>
   130    auto internal_then(FT &&f) -> typename std::enable_if<
   131        is_function_with_arg_type<FT, RT>::value,
   132        typename std::remove_reference<
   133            typename function_res_traits<FT>::ret_type>::type &&>::type {
   134      return std::move(f(m_pImpl->get()));
   135    }
   136  
   137   protected:
   138     using ::ff::internal::para_common<para<RT>, RT>::m_pImpl;
   139  };  // end class para;
   140  
   141  template <>
   142  class para<void> : public ::ff::internal::para_common<para<void>, void> {
   143  public:
   144    typedef void ret_type;
   145    template <class FT>
   146    auto internal_then(FT &&f) -> typename std::enable_if<
   147        std::is_void<typename function_res_traits<FT>::ret_type>::value &&
   148            is_function_with_arg_type<FT, void>::value,
   149        void>::type {
   150      f();
   151    }
   152  
   153    template <class FT>
   154    auto internal_then(FT &&f) -> typename std::enable_if<
   155        is_function_with_arg_type<FT, void>::value &&
   156            !std::is_void<typename function_res_traits<FT>::ret_type>::value,
   157        typename std::remove_reference<
   158            typename function_res_traits<FT>::ret_type>::type>::type {
   159      return f();
   160    }
   161  };  // end class para;
   162  
   163  template <class T>
   164  class para<para<T>> {
   165   public:
   166    para() {
   167      static_assert(Please_Check_The_Assert_Msg<para<T>>::value,
   168                    FF_EM_CALL_NO_SUPPORT_FOR_PARA);
   169    };
   170  };  // end class para;
   171  
   172  }  // end namespace ff