|
||||
File indexing completed on 2025-01-18 09:51:46
0001 //---------------------------------------------------------------------------- 0002 /// @file scheduler.hpp 0003 /// @brief This file contains the implementation of the scheduler for 0004 /// dispatch the works stored 0005 /// 0006 /// @author Copyright (c) 2010 2015 Francisco José Tapia (fjtapia@gmail.com )\n 0007 /// Distributed under the Boost Software License, Version 1.0.\n 0008 /// ( See accompanyingfile LICENSE_1_0.txt or copy at 0009 /// http://www.boost.org/LICENSE_1_0.txt ) 0010 /// @version 0.1 0011 /// 0012 /// @remarks 0013 //----------------------------------------------------------------------------- 0014 #ifndef __BOOST_SORT_COMMON_SCHEDULER_HPP 0015 #define __BOOST_SORT_COMMON_SCHEDULER_HPP 0016 0017 #include <ciso646> 0018 #include <scoped_allocator> 0019 #include <utility> 0020 #include <vector> 0021 #include <deque> 0022 #include <iostream> 0023 #include <unordered_map> 0024 #include <boost/sort/common/spinlock.hpp> 0025 #include <boost/sort/common/util/search.hpp> 0026 #include <boost/sort/common/util/traits.hpp> 0027 0028 namespace boost 0029 { 0030 namespace sort 0031 { 0032 namespace common 0033 { 0034 0035 // 0036 //########################################################################### 0037 // ## 0038 // ################################################################ ## 0039 // # # ## 0040 // # C L A S S S C H E D U L E R # ## 0041 // # # ## 0042 // ################################################################ ## 0043 // ## 0044 //########################################################################### 0045 0046 // 0047 //--------------------------------------------------------------------------- 0048 /// @class scheduler 0049 /// @brief This class is a concurrent stack controled by a spin_lock 0050 /// @remarks 0051 //--------------------------------------------------------------------------- 0052 template<typename Func_t, typename Allocator = std::allocator<Func_t> > 0053 struct scheduler 0054 { 0055 //----------------------------------------------------------------------- 0056 // D E F I N I T I O N S 0057 //----------------------------------------------------------------------- 0058 typedef std::scoped_allocator_adaptor <Allocator> scoped_alloc; 0059 template <class T> 0060 using alloc_t = typename std::allocator_traits<Allocator>:: 0061 template rebind_alloc<T>; 0062 0063 0064 typedef std::deque <Func_t, scoped_alloc> deque_t; 0065 typedef typename deque_t::iterator it_deque; 0066 typedef std::thread::id key_t; 0067 typedef std::hash <key_t> hash_t; 0068 typedef std::equal_to <key_t> equal_t; 0069 typedef std::unique_lock <spinlock_t> lock_t; 0070 typedef std::pair<const key_t, deque_t> pair_t; 0071 0072 typedef std::unordered_map <key_t, deque_t, hash_t, 0073 equal_t, alloc_t <pair_t> > map_t; 0074 typedef typename map_t::iterator it_map; 0075 0076 //----------------------------------------------------------------------- 0077 // V A R I A B L E S 0078 //----------------------------------------------------------------------- 0079 map_t mp; 0080 size_t nelem; 0081 mutable spinlock_t spl; 0082 0083 //------------------------------------------------------------------------ 0084 // function : scheduler 0085 /// @brief constructor 0086 //------------------------------------------------------------------------ 0087 scheduler(void) : mp(), nelem(0) { }; 0088 // 0089 //----------------------------------------------------------------------- 0090 // function : scheduler 0091 /// @brief Copy & move constructor 0092 /// @param [in] VT : stack_cnc from where copy the data 0093 //----------------------------------------------------------------------- 0094 scheduler(scheduler && VT) = delete; 0095 scheduler(const scheduler & VT) = delete; 0096 // 0097 //------------------------------------------------------------------------ 0098 // function : ~scheduler 0099 /// @brief Destructor 0100 //------------------------------------------------------------------------ 0101 virtual ~scheduler(void) {mp.clear();}; 0102 // 0103 //------------------------------------------------------------------------ 0104 // function : operator = 0105 /// @brief Asignation operator 0106 /// @param [in] VT : stack_cnc from where copy the data 0107 /// @return Reference to the stack_cnc after the copy 0108 //------------------------------------------------------------------------ 0109 scheduler & operator=(const scheduler &VT) = delete; 0110 // 0111 //------------------------------------------------------------------------ 0112 // function : size 0113 /// @brief Asignation operator 0114 /// @param [in] VT : stack_cnc from where copy the data 0115 /// @return Reference to the stack_cnc after the copy 0116 //------------------------------------------------------------------------ 0117 size_t size(void) const 0118 { 0119 lock_t s(spl); 0120 return nelem; 0121 }; 0122 // 0123 //------------------------------------------------------------------------ 0124 // function : clear 0125 /// @brief Delete all the elements of the stack_cnc. 0126 //------------------------------------------------------------------------ 0127 void clear_all(void) 0128 { 0129 lock_t s(spl); 0130 mp.clear(); 0131 nelem = 0; 0132 }; 0133 0134 // 0135 //------------------------------------------------------------------------ 0136 // function : insert 0137 /// @brief Insert one element in the back of the container 0138 /// @param [in] D : value to insert. Can ve a value, a reference or an 0139 /// rvalue 0140 /// @return iterator to the element inserted 0141 /// @remarks This operation is O ( const ) 0142 //------------------------------------------------------------------------ 0143 void insert(Func_t & f) 0144 { 0145 lock_t s(spl); 0146 key_t th_id = std::this_thread::get_id(); 0147 it_map itmp = mp.find(th_id); 0148 if (itmp == mp.end()) 0149 { 0150 auto aux = mp.emplace(th_id, deque_t()); 0151 if (aux.second == false) throw std::bad_alloc(); 0152 itmp = aux.first; 0153 }; 0154 itmp->second.emplace_back(std::move(f)); 0155 nelem++; 0156 }; 0157 0158 // 0159 //------------------------------------------------------------------------ 0160 // function :emplace 0161 /// @brief Insert one element in the back of the container 0162 /// @param [in] args :group of arguments for to build the object to insert 0163 /// @return iterator to the element inserted 0164 /// @remarks This operation is O ( const ) 0165 //------------------------------------------------------------------------ 0166 template<class ... Args> 0167 void emplace(Args && ... args) 0168 { 0169 lock_t s(spl); 0170 key_t th_id = std::this_thread::get_id(); 0171 it_map itmp = mp.find(th_id); 0172 if (itmp == mp.end()) 0173 { 0174 auto aux = mp.emplace(th_id, deque_t()); 0175 if (aux.second == false) throw std::bad_alloc(); 0176 itmp = aux.first; 0177 }; 0178 itmp->second.emplace_back(std::forward <Args>(args) ...); 0179 nelem++; 0180 }; 0181 // 0182 //------------------------------------------------------------------------ 0183 // function : insert 0184 /// @brief Insert one element in the back of the container 0185 /// @param [in] D : value to insert. Can ve a value, a reference or an rvalue 0186 /// @return iterator to the element inserted 0187 /// @remarks This operation is O ( const ) 0188 //------------------------------------------------------------------------ 0189 template<class it_func> 0190 void insert_range(it_func first, it_func last) 0191 { 0192 //-------------------------------------------------------------------- 0193 // Metaprogramming 0194 //-------------------------------------------------------------------- 0195 typedef util::value_iter<it_func> value2_t; 0196 static_assert (std::is_same< Func_t, value2_t >::value, 0197 "Incompatible iterators\n"); 0198 0199 //-------------------------------------------------------------------- 0200 // Code 0201 //-------------------------------------------------------------------- 0202 assert((last - first) > 0); 0203 0204 lock_t s(spl); 0205 key_t th_id = std::this_thread::get_id(); 0206 it_map itmp = mp.find(th_id); 0207 if (itmp == mp.end()) 0208 { 0209 auto aux = mp.emplace(th_id, deque_t()); 0210 if (aux.second == true) throw std::bad_alloc(); 0211 itmp = aux.first; 0212 }; 0213 while (first != last) 0214 { 0215 itmp->second.emplace_back(std::move(*(first++))); 0216 nelem++; 0217 }; 0218 }; 0219 // 0220 //------------------------------------------------------------------------ 0221 // function : extract 0222 /// @brief erase the last element of the tree and return a copy 0223 /// @param [out] V : reference to a variable where copy the element 0224 /// @return code of the operation 0225 /// 0- Element erased 0226 /// 1 - Empty tree 0227 /// @remarks This operation is O(1) 0228 //------------------------------------------------------------------------ 0229 bool extract(Func_t & f) 0230 { 0231 lock_t s(spl); 0232 if (nelem == 0) return false; 0233 key_t th_id = std::this_thread::get_id(); 0234 it_map itmp = mp.find(th_id); 0235 if (itmp != mp.end() and not itmp->second.empty()) 0236 { 0237 f = std::move(itmp->second.back()); 0238 itmp->second.pop_back(); 0239 --nelem; 0240 return true; 0241 }; 0242 for (itmp = mp.begin(); itmp != mp.end(); ++itmp) 0243 { 0244 if (itmp->second.empty()) continue; 0245 f = std::move(itmp->second.back()); 0246 itmp->second.pop_back(); 0247 --nelem; 0248 return true; 0249 } 0250 return false; 0251 }; 0252 }; 0253 // end class scheduler 0254 //************************************************************************* 0255 // P R I N T F U N C T I O N S 0256 //************************************************************************ 0257 template<class ... Args> 0258 std::ostream & operator <<(std::ostream &out, const std::deque<Args ...> & dq) 0259 { 0260 for (uint32_t i = 0; i < dq.size(); ++i) 0261 out << dq[i] << " "; 0262 out << std::endl; 0263 return out; 0264 } 0265 0266 template<typename Func_t, typename Allocator = std::allocator<Func_t> > 0267 std::ostream & operator <<(std::ostream &out, 0268 const scheduler<Func_t, Allocator> &sch) 0269 { 0270 std::unique_lock < spinlock_t > s(sch.spl); 0271 out << "Nelem :" << sch.nelem << std::endl; 0272 for (auto it = sch.mp.begin(); it != sch.mp.end(); ++it) 0273 { 0274 out << it->first << " :" << it->second << std::endl; 0275 } 0276 return out; 0277 } 0278 0279 //*************************************************************************** 0280 };// end namespace common 0281 };// end namespace sort 0282 };// end namespace boost 0283 //*************************************************************************** 0284 #endif
[ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
This page was automatically generated by the 2.3.7 LXR engine. The LXR team |