github.com/igggame/nebulas-go@v2.1.0+incompatible/nbre/3rd_party/fflib/include/ff/functionflow/para/paragroup.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  #ifndef FF_PARA_PARA_GROUND_H_
    25  #define FF_PARA_PARA_GROUND_H_
    26  #include "ff/functionflow/common/common.h"
    27  #include "ff/functionflow/common/error_msg.h"
    28  #include "ff/functionflow/para/para.h"
    29  #include "ff/functionflow/para/para_helper.h"
    30  #include "ff/functionflow/para/paras_with_lock.h"
    31  #include "ff/functionflow/para/wait_impl.h"
    32  #include "ff/functionflow/runtime/rtcmn.h"
    33  #include "ff/util/func_type_checker.h"
    34  #include "ff/util/is_callable.h"
    35  
    36  #include <cmath>
    37  #include <algorithm>
    38  
    39  namespace ff {
    40  
    41  namespace internal {
    42  class wait_all;
    43  class wait_any;
    44  }  // end namespace internal
    45  struct auto_partitioner {};
    46  struct simple_partitioner {};
    47  
    48  class paragroup {
    49   public:
    50    typedef void ret_type;
    51  
    52   public:
    53    template <class PT, class WT>
    54    class para_accepted_wait {
    55      para_accepted_wait &operator=(const para_accepted_wait<PT, WT> &) = delete;
    56  
    57     public:
    58      typedef typename PT::ret_type ret_type;
    59      para_accepted_wait(const para_accepted_wait<PT, WT> &) = default;
    60      para_accepted_wait(PT &p, const WT &w) : m_refP(p), m_oWaiting(w) {}
    61  
    62      //! For arithmetic iterators
    63      template <class Iterator_t, class Functor_t>
    64      auto for_each(Iterator_t begin, Iterator_t end, Functor_t &&f) ->
    65          typename std::enable_if<
    66              std::is_arithmetic<
    67                  typename std::remove_cv<Iterator_t>::type>::value,
    68              ::ff::internal::para_accepted_call<paragroup, void>>::type {
    69        FF_DEFAULT_PARTITIONER *p = nullptr;
    70        for_each_impl(begin, end, std::forward<Functor_t>(f), m_refP.m_pEntities,
    71                      p);
    72        // for_each_impl_general_iterator(begin, end, std::forward<Functor_t>(f),
    73        // m_refP.m_pEntities, p);
    74        return ::ff::internal::para_accepted_call<paragroup, ret_type>(m_refP);
    75      }
    76  
    77      //! For random-access iterators
    78      template <class Iterator_t, class Functor_t>
    79      auto for_each(Iterator_t begin, Iterator_t end, Functor_t &&f) ->
    80          typename std::enable_if<
    81              !std::is_arithmetic<
    82                  typename std::remove_cv<Iterator_t>::type>::value &&
    83                  std::is_same<typename std::iterator_traits<
    84                                   Iterator_t>::iterator_category,
    85                               std::random_access_iterator_tag>::value,
    86              ::ff::internal::para_accepted_call<paragroup, void>>::type {
    87        FF_DEFAULT_PARTITIONER *p = nullptr;
    88        for_each_impl(begin, end, [f](const Iterator_t &t) {
    89          // for_each_impl_general_iterator(begin, end, [f](const Iterator_t & t)
    90          // {
    91          f(*t);
    92        }, m_refP.m_pEntities, p);
    93        return ::ff::internal::para_accepted_call<paragroup, ret_type>(m_refP);
    94      }
    95  
    96      //! For general iterators
    97      template <class Iterator_t, class Functor_t>
    98      auto for_each(Iterator_t begin, Iterator_t end, Functor_t &&f) ->
    99          typename std::enable_if<
   100              !std::is_arithmetic<
   101                  typename std::remove_cv<Iterator_t>::type>::value &&
   102                  !std::is_same<typename std::iterator_traits<
   103                                    Iterator_t>::iterator_category,
   104                                std::random_access_iterator_tag>::value,
   105              ::ff::internal::para_accepted_call<paragroup, void>>::type {
   106        FF_DEFAULT_PARTITIONER *p = nullptr;
   107        for_each_impl_general_iterator(begin, end, [f](const Iterator_t &t) {
   108          f(*t);
   109        }, m_refP.m_pEntities, p);
   110        return ::ff::internal::para_accepted_call<paragroup, ret_type>(m_refP);
   111      }
   112  
   113     protected:
   114      PT &m_refP;
   115      WT m_oWaiting;
   116    };  // end class para_accepted_wait;
   117  
   118    template <class WT>
   119    para_accepted_wait<paragroup, WT> operator[](WT &&cond) {
   120      return para_accepted_wait<paragroup, WT>(*this, std::forward<WT>(cond));
   121    }
   122    //! For input index, return the corresponding task
   123    para<void> &operator[](int index) { return (*m_pEntities).entities[index]; }
   124  
   125    size_t size() const {
   126      if (m_pEntities) return m_pEntities->entities.size();
   127      return 0;
   128    }
   129  
   130    ~paragroup() {
   131      ::ff::internal::wait_all wa(m_pEntities);
   132      wa.then([]() {});
   133    }
   134  
   135    //! For arithmetic iterator
   136    template <class Iterator_t, class Functor_t>
   137    auto for_each(Iterator_t begin, Iterator_t end, Functor_t &&f) ->
   138        typename std::enable_if<
   139            std::is_arithmetic<
   140                typename std::remove_cv<Iterator_t>::type>::value &&
   141                ff::util::is_function_with_arg_type<Functor_t, Iterator_t>::value,
   142            ::ff::internal::para_accepted_call<paragroup, void>>::type {
   143      FF_DEFAULT_PARTITIONER *p = nullptr;
   144      for_each_impl(begin, end, std::forward<Functor_t>(f), m_pEntities, p);
   145      // for_each_impl_general_iterator(begin, end, std::forward<Functor_t>(f),
   146      // m_pEntities, p);
   147      return ::ff::internal::para_accepted_call<paragroup, ret_type>(*this);
   148    }
   149  
   150    //! For random-access iterator
   151    template <class Iterator_t, class Functor_t>
   152    auto for_each(Iterator_t begin, Iterator_t end, Functor_t &&f) ->
   153        typename std::enable_if<
   154            !std::is_arithmetic<
   155                typename std::remove_cv<Iterator_t>::type>::value &&
   156                std::is_same<
   157                    typename std::iterator_traits<Iterator_t>::iterator_category,
   158                    std::random_access_iterator_tag>::value &&
   159                ff::util::is_function_with_arg_type<
   160                    Functor_t,
   161                    typename std::iterator_traits<Iterator_t>::value_type>::value,
   162            ::ff::internal::para_accepted_call<paragroup, void>>::type {
   163      FF_DEFAULT_PARTITIONER *p = nullptr;
   164      for_each_impl(begin, end, [f](const Iterator_t &t) {
   165        // for_each_impl_general_iterator(begin, end, [f](const Iterator_t & t) {
   166        f(*t);
   167      }, m_pEntities, p);
   168      return ::ff::internal::para_accepted_call<paragroup, ret_type>(*this);
   169    }
   170  
   171    //! For general iterator
   172    template <class Iterator_t, class Functor_t>
   173    auto for_each(Iterator_t begin, Iterator_t end, Functor_t &&f) ->
   174        typename std::enable_if<
   175            !std::is_arithmetic<
   176                typename std::remove_cv<Iterator_t>::type>::value &&
   177                !std::is_same<
   178                    typename std::iterator_traits<Iterator_t>::iterator_category,
   179                    std::random_access_iterator_tag>::value &&
   180                ff::util::is_function_with_arg_type<
   181                    Functor_t,
   182                    typename std::iterator_traits<Iterator_t>::value_type>::value,
   183            ::ff::internal::para_accepted_call<paragroup, void>>::type {
   184      FF_DEFAULT_PARTITIONER *p = nullptr;
   185      for_each_impl_general_iterator(
   186          begin, end, [f](const Iterator_t &t) { f(*t); }, m_pEntities, p);
   187      return ::ff::internal::para_accepted_call<paragroup, ret_type>(*this);
   188    }
   189  
   190    template <class Iterator_t, class Functor_t>
   191    auto for_each(Iterator_t begin, Iterator_t end, Functor_t &&f) ->
   192        typename std::enable_if<
   193            !ff::util::is_callable<Functor_t>::value,
   194            ::ff::internal::para_accepted_call<paragroup, void>>::type {
   195      static_assert(Please_Check_The_Assert_Msg<Functor_t>::value,
   196                    FF_EM_CALL_FOR_EACH_WITHOUT_FUNCTION);
   197    }
   198  
   199    template <class Iterator_t, class Functor_t>
   200    auto for_each(Iterator_t begin, Iterator_t end, Functor_t &&f) ->
   201        typename std::enable_if<
   202            ff::util::is_callable<Functor_t>::value &&
   203                std::is_arithmetic<
   204                    typename std::remove_cv<Iterator_t>::type>::value &&
   205                !ff::util::is_function_with_arg_type<Functor_t,
   206                                                     Iterator_t>::value,
   207            ::ff::internal::para_accepted_call<paragroup, void>>::type {
   208      static_assert(Please_Check_The_Assert_Msg<Functor_t>::value,
   209                    FF_EM_CALL_FOR_EACH_WRONG_FUNCTION);
   210    }
   211  
   212    template <class Iterator_t, class Functor_t>
   213    auto for_each(Iterator_t begin, Iterator_t end, Functor_t &&f) ->
   214        typename std::enable_if<
   215            ff::util::is_callable<Functor_t>::value &&
   216                !ff::util::is_function_with_arg_type<
   217                    Functor_t,
   218                    typename std::iterator_traits<Iterator_t>::value_type>::value,
   219            ::ff::internal::para_accepted_call<paragroup, void>>::type {
   220      static_assert(Please_Check_The_Assert_Msg<Functor_t>::value,
   221                    FF_EM_CALL_FOR_EACH_WRONG_FUNCTION);
   222    }
   223  
   224    void clear() { m_pEntities.reset(); }
   225    template <class T>
   226    void add(T &&t) {
   227      static_assert(Please_Check_The_Assert_Msg<T>::value,
   228                    FF_EM_USE_PARACONTAINER_INSTEAD_OF_GROUP);
   229    }
   230  
   231   protected:
   232     typedef std::shared_ptr<::ff::internal::paras_with_lock> Entities_t;
   233  
   234  #include "ff/functionflow/para/paragroup_general_iterator_impl.h"
   235  
   236  #include "ff/functionflow/para/paragroup_random_access_iterator.h"
   237  
   238   protected:
   239     friend ::ff::internal::wait_all all(paragroup &pg);
   240     friend ::ff::internal::wait_any any(paragroup &pg);
   241     std::shared_ptr<::ff::internal::paras_with_lock> &all_entities() {
   242       return m_pEntities;
   243     };
   244  
   245   protected:
   246     std::shared_ptr<::ff::internal::paras_with_lock> m_pEntities;
   247  };  // end class paragroup
   248  
   249  }  // end namespace ff
   250  
   251  #endif