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