Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-30 10:01:11

0001 // Copyright (C) 2015 Vicente J. Botet Escriba
0002 //
0003 //  Distributed under the Boost Software License, Version 1.0. (See accompanying
0004 //  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
0005 //
0006 // 2013/11 Vicente J. Botet Escriba
0007 //    first implementation of a simple serial scheduler.
0008 
0009 #ifndef BOOST_THREAD_SERIAL_EXECUTOR_CONT_HPP
0010 #define BOOST_THREAD_SERIAL_EXECUTOR_CONT_HPP
0011 
0012 #include <boost/thread/detail/config.hpp>
0013 #if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION && defined BOOST_THREAD_PROVIDES_EXECUTORS && defined BOOST_THREAD_USES_MOVE
0014 
0015 #include <exception> // std::terminate
0016 #include <boost/throw_exception.hpp>
0017 #include <boost/thread/detail/delete.hpp>
0018 #include <boost/thread/detail/move.hpp>
0019 #include <boost/thread/concurrent_queues/sync_queue.hpp>
0020 #include <boost/thread/executors/work.hpp>
0021 #include <boost/thread/executors/generic_executor_ref.hpp>
0022 #include <boost/thread/mutex.hpp>
0023 #include <boost/thread/future.hpp>
0024 #include <boost/thread/scoped_thread.hpp>
0025 #include <boost/thread/lock_guard.hpp>
0026 
0027 #include <boost/config/abi_prefix.hpp>
0028 
0029 namespace boost
0030 {
0031 namespace executors
0032 {
0033   class serial_executor_cont
0034   {
0035   public:
0036     /// type-erasure to store the works to do
0037     typedef  executors::work work;
0038   private:
0039 
0040     generic_executor_ref ex_;
0041     BOOST_THREAD_FUTURE<void> fut_; // protected by mtx_
0042     bool closed_; // protected by mtx_
0043     mutex mtx_;
0044 
0045     struct continuation {
0046       work task;
0047       template <class X>
0048       struct result {
0049         typedef void type;
0050       };
0051       continuation(BOOST_THREAD_RV_REF(work) tsk)
0052       : task(boost::move(tsk)) {}
0053       void operator()(BOOST_THREAD_FUTURE<void> f)
0054       {
0055         try {
0056           task();
0057         } catch (...)  {
0058           std::terminate();
0059         }
0060       }
0061     };
0062 
0063     bool closed(lock_guard<mutex>&) const
0064     {
0065       return closed_;
0066     }
0067   public:
0068     /**
0069      * \par Returns
0070      * The underlying executor wrapped on a generic executor reference.
0071      */
0072     generic_executor_ref& underlying_executor() BOOST_NOEXCEPT { return ex_; }
0073 
0074     /// serial_executor_cont is not copyable.
0075     BOOST_THREAD_NO_COPYABLE(serial_executor_cont)
0076 
0077     /**
0078      * \b Effects: creates a serial executor that runs closures in fifo order using one the associated executor.
0079      *
0080      * \b Throws: Whatever exception is thrown while initializing the needed resources.
0081      *
0082      * \b Notes:
0083      * * The lifetime of the associated executor must outlive the serial executor.
0084      * * The current implementation doesn't support submission from synchronous continuation, that is,
0085      *     - the executor must execute the continuation asynchronously or
0086      *     - the continuation can not submit to this serial executor.
0087      */
0088     template <class Executor>
0089     serial_executor_cont(Executor& ex)
0090     : ex_(ex), fut_(make_ready_future()), closed_(false)
0091     {
0092     }
0093     /**
0094      * \b Effects: Destroys the thread pool.
0095      *
0096      * \b Synchronization: The completion of all the closures happen before the completion of the \c serial_executor_cont destructor.
0097      */
0098     ~serial_executor_cont()
0099     {
0100       // signal to the worker thread that there will be no more submissions.
0101       close();
0102     }
0103 
0104     /**
0105      * \b Effects: close the \c serial_executor_cont for submissions.
0106      * The loop will work until there is no more closures to run.
0107      */
0108     void close()
0109     {
0110       lock_guard<mutex> lk(mtx_);
0111       closed_ = true;;
0112     }
0113 
0114     /**
0115      * \b Returns: whether the pool is closed for submissions.
0116      */
0117     bool closed()
0118     {
0119       lock_guard<mutex> lk(mtx_);
0120       return closed(lk);
0121     }
0122 
0123     /**
0124      * Effects: none.
0125      * Returns: always false.
0126      * Throws: No.
0127      * Remark: A serial executor can not execute one of its pending tasks as the tasks depends on the other tasks.
0128      */
0129     bool try_executing_one()
0130     {
0131       return false;
0132     }
0133 
0134     /**
0135      * \b Requires: \c Closure is a model of \c Callable(void()) and a model of \c CopyConstructible/MoveConstructible.
0136      *
0137      * \b Effects: The specified \c closure will be scheduled for execution after the last submitted closure finish.
0138      * If the invoked closure throws an exception the \c serial_executor_cont will call \c std::terminate, as is the case with threads.
0139      *
0140      * \b Throws: \c sync_queue_is_closed if the executor is closed.
0141      * Whatever exception that can be throw while storing the closure.
0142      *
0143      */
0144 
0145 #if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
0146     template <typename Closure>
0147     void submit(Closure & closure)
0148     {
0149       lock_guard<mutex> lk(mtx_);
0150       if (closed(lk))       BOOST_THROW_EXCEPTION( sync_queue_is_closed() );
0151       fut_ = fut_.then(ex_, continuation(work(closure)));
0152     }
0153 #endif
0154     void submit(void (*closure)())
0155     {
0156       lock_guard<mutex> lk(mtx_);
0157       if (closed(lk))       BOOST_THROW_EXCEPTION( sync_queue_is_closed() );
0158       fut_ = fut_.then(ex_, continuation(work(closure)));
0159     }
0160 
0161     template <typename Closure>
0162     void submit(BOOST_THREAD_FWD_REF(Closure) closure)
0163     {
0164       lock_guard<mutex> lk(mtx_);
0165       if (closed(lk))       BOOST_THROW_EXCEPTION( sync_queue_is_closed() );
0166       fut_ = fut_.then(ex_, continuation(work(boost::forward<Closure>(closure))));
0167     }
0168 
0169   };
0170 }
0171 using executors::serial_executor_cont;
0172 }
0173 
0174 #include <boost/config/abi_suffix.hpp>
0175 
0176 #endif
0177 #endif