Back to home page

EIC code displayed by LXR

 
 

    


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