Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 10:15:37

0001 //------------------------------------------------------------------------------
0002 // Copyright (c) 2011-2014 by European Organization for Nuclear Research (CERN)
0003 // Author: Michal Simon <michal.simon@cern.ch>
0004 //------------------------------------------------------------------------------
0005 // This file is part of the XRootD software suite.
0006 //
0007 // XRootD is free software: you can redistribute it and/or modify
0008 // it under the terms of the GNU Lesser General Public License as published by
0009 // the Free Software Foundation, either version 3 of the License, or
0010 // (at your option) any later version.
0011 //
0012 // XRootD is distributed in the hope that it will be useful,
0013 // but WITHOUT ANY WARRANTY; without even the implied warranty of
0014 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
0015 // GNU General Public License for more details.
0016 //
0017 // You should have received a copy of the GNU Lesser General Public License
0018 // along with XRootD.  If not, see <http://www.gnu.org/licenses/>.
0019 //
0020 // In applying this licence, CERN does not waive the privileges and immunities
0021 // granted to it by virtue of its status as an Intergovernmental Organization
0022 // or submit itself to any jurisdiction.
0023 //------------------------------------------------------------------------------
0024 
0025 #include "XrdCl/XrdClJobManager.hh"
0026 
0027 #include <future>
0028 #include <type_traits>
0029 
0030 #ifndef SRC_XRDEC_XRDECTHREADPOOL_HH_
0031 #define SRC_XRDEC_XRDECTHREADPOOL_HH_
0032 
0033 namespace XrdEc
0034 {
0035   //---------------------------------------------------------------------------
0036   // A theread pool class for the XrdEc module
0037   //---------------------------------------------------------------------------
0038   class ThreadPool
0039   {
0040     private:
0041 
0042       // This is the type which holds sequences
0043       template<int ... Is> struct sequence {};
0044 
0045       // First define the template signature
0046       template <int ... Ns> struct seq_gen;
0047 
0048       // Recursion case
0049       template <int I, int ... Ns>
0050       struct seq_gen<I, Ns...>
0051       {
0052         using type = typename seq_gen<I - 1, I - 1, Ns...>::type;
0053       };
0054 
0055       // Recursion abort
0056       template <int ... Ns>
0057       struct seq_gen<0, Ns...>
0058       {
0059         using type = sequence<Ns...>;
0060       };
0061 
0062       // call functional with arguments in a tuple (implementation)
0063       template <typename FUNC, typename TUPL, int ... INDICES>
0064       inline static auto tuple_call_impl( FUNC &func, TUPL &args, sequence<INDICES...> ) -> decltype( func( std::move( std::get<INDICES>( args ) )... ) )
0065       {
0066         return func( std::move( std::get<INDICES>( args ) )... );
0067       }
0068 
0069       // call functional with argumetns packaged in a tuple
0070       template <typename FUNC, typename ... ARGs>
0071       inline static auto tuple_call( FUNC &func, std::tuple<ARGs...> &tup ) ->decltype( tuple_call_impl( func, tup, typename seq_gen<sizeof...(ARGs)>::type{} ) )
0072       {
0073         return tuple_call_impl( func, tup, typename seq_gen<sizeof...(ARGs)>::type{} );
0074       }
0075 
0076       //-----------------------------------------------------------------------
0077       // Helper class implementing a job containing any functional and its
0078       // arguments.
0079       //-----------------------------------------------------------------------
0080       template<typename FUNC, typename RET, typename ... ARGs>
0081       class AnyJob : public XrdCl::Job
0082       {
0083         //---------------------------------------------------------------------
0084         // Run the functional (returning void) with the packaged arguments
0085         //---------------------------------------------------------------------
0086         static inline void RunImpl( FUNC func, std::tuple<ARGs...> &args, std::promise<void> &prms )
0087         {
0088           tuple_call( func, args );
0089           prms.set_value();
0090         }
0091 
0092         //---------------------------------------------------------------------
0093         // Run the functional (returning anything but void) with the packaged
0094         // arguments
0095         //---------------------------------------------------------------------
0096         template<typename RETURN>
0097         static inline void RunImpl( FUNC func, std::tuple<ARGs...> &args, std::promise<RETURN> &prms )
0098         {
0099           prms.set_value( tuple_call( func, args ) );
0100         }
0101 
0102         public:
0103           //-------------------------------------------------------------------
0104           //! Constructor
0105           //!
0106           //! @param func : functional to be called
0107           //! @param args : arguments for the functional
0108           //-------------------------------------------------------------------
0109           AnyJob( FUNC func, ARGs... args ) : func( std::move( func ) ),
0110                                               args( std::tuple<ARGs...>( std::move( args )... ) )
0111           {
0112           }
0113 
0114           //-------------------------------------------------------------------
0115           //! Run the job
0116           //-------------------------------------------------------------------
0117           void Run( void *arg )
0118           {
0119             RunImpl( this->func, this->args, this->prms );
0120             delete this;
0121           }
0122 
0123           //-------------------------------------------------------------------
0124           //! Get the future result of the job
0125           //-------------------------------------------------------------------
0126           std::future<RET> GetFuture()
0127           {
0128             return prms.get_future();
0129           }
0130 
0131         protected:
0132 
0133           FUNC                func; //< the functional
0134           std::tuple<ARGs...> args; //< the arguments
0135           std::promise<RET>   prms; //< the promiss that there will be a result
0136       };
0137 
0138     public:
0139 
0140       //-----------------------------------------------------------------------
0141       //! Destructor
0142       //-----------------------------------------------------------------------
0143       ~ThreadPool()
0144       {
0145         threadpool.Stop();
0146         threadpool.Finalize();
0147       }
0148 
0149       //-----------------------------------------------------------------------
0150       //! Singleton access
0151       //-----------------------------------------------------------------------
0152       static ThreadPool& Instance()
0153       {
0154         static ThreadPool instance;
0155         return instance;
0156       }
0157 
0158       //-----------------------------------------------------------------------
0159       //! Schedule a functional (together with its arguments) for execution
0160       //-----------------------------------------------------------------------
0161       template<typename FUNC, typename ... ARGs>
0162       inline std::future<std::invoke_result_t<FUNC, ARGs...>>
0163       Execute( FUNC func, ARGs... args )
0164       {
0165         using RET = std::invoke_result_t<FUNC, ARGs...>;
0166         auto *job = new AnyJob<FUNC, RET, ARGs...>( func, std::move( args )... );
0167         std::future<RET> ftr = job->GetFuture();
0168         threadpool.QueueJob( job, nullptr );
0169         return ftr;
0170       }
0171 
0172     private:
0173 
0174       //-----------------------------------------------------------------------
0175       //! Constructor
0176       //-----------------------------------------------------------------------
0177       ThreadPool() : threadpool( 64 )
0178       {
0179         threadpool.Initialize();
0180         threadpool.Start();
0181       }
0182 
0183       XrdCl::JobManager threadpool; //< the thread-pool itself
0184   };
0185 
0186 }
0187 
0188 
0189 #endif /* SRC_XRDEC_XRDECTHREADPOOL_HH_ */