159 lines
		
	
	
		
			4.9 KiB
		
	
	
	
		
			C++
		
	
	
	
		
		
			
		
	
	
			159 lines
		
	
	
		
			4.9 KiB
		
	
	
	
		
			C++
		
	
	
	
|  | //          Copyright Oliver Kowalke 2013.
 | ||
|  | // Distributed under the Boost Software License, Version 1.0.
 | ||
|  | //    (See accompanying file LICENSE_1_0.txt or copy at
 | ||
|  | //          http://www.boost.org/LICENSE_1_0.txt)
 | ||
|  | 
 | ||
|  | #ifndef BOOST_FIBERS_FIBER_MANAGER_H
 | ||
|  | #define BOOST_FIBERS_FIBER_MANAGER_H
 | ||
|  | 
 | ||
|  | #include <chrono>
 | ||
|  | #include <functional>
 | ||
|  | #include <memory>
 | ||
|  | #include <mutex>
 | ||
|  | #include <vector>
 | ||
|  | 
 | ||
|  | #include <boost/config.hpp>
 | ||
|  | #include <boost/context/execution_context.hpp>
 | ||
|  | #include <boost/intrusive/list.hpp>
 | ||
|  | #include <boost/intrusive_ptr.hpp>
 | ||
|  | #include <boost/intrusive/set.hpp>
 | ||
|  | 
 | ||
|  | #include <boost/fiber/algo/algorithm.hpp>
 | ||
|  | #include <boost/fiber/context.hpp>
 | ||
|  | #include <boost/fiber/detail/config.hpp>
 | ||
|  | #include <boost/fiber/detail/context_mpsc_queue.hpp>
 | ||
|  | #include <boost/fiber/detail/data.hpp>
 | ||
|  | #include <boost/fiber/detail/spinlock.hpp>
 | ||
|  | 
 | ||
|  | #ifdef BOOST_HAS_ABI_HEADERS
 | ||
|  | #  include BOOST_ABI_PREFIX
 | ||
|  | #endif
 | ||
|  | 
 | ||
|  | #ifdef _MSC_VER
 | ||
|  | # pragma warning(push)
 | ||
|  | # pragma warning(disable:4251)
 | ||
|  | #endif
 | ||
|  | 
 | ||
|  | namespace boost { | ||
|  | namespace fibers { | ||
|  | 
 | ||
|  | class BOOST_FIBERS_DECL scheduler { | ||
|  | public: | ||
|  |     struct timepoint_less { | ||
|  |         bool operator()( context const& l, context const& r) const noexcept { | ||
|  |             return l.tp_ < r.tp_; | ||
|  |         } | ||
|  |     }; | ||
|  | 
 | ||
|  |     typedef intrusive::list< | ||
|  |                 context, | ||
|  |                 intrusive::member_hook< | ||
|  |                     context, detail::ready_hook, & context::ready_hook_ >, | ||
|  |                 intrusive::constant_time_size< false > >    ready_queue_t; | ||
|  | private: | ||
|  |     typedef intrusive::multiset< | ||
|  |                 context, | ||
|  |                 intrusive::member_hook< | ||
|  |                     context, detail::sleep_hook, & context::sleep_hook_ >, | ||
|  |                 intrusive::constant_time_size< false >, | ||
|  |                 intrusive::compare< timepoint_less > >      sleep_queue_t; | ||
|  |     typedef intrusive::list< | ||
|  |                 context, | ||
|  |                 intrusive::member_hook< | ||
|  |                     context, detail::terminated_hook, & context::terminated_hook_ >, | ||
|  |                 intrusive::constant_time_size< false > >    terminated_queue_t; | ||
|  |     typedef intrusive::list< | ||
|  |                 context, | ||
|  |                 intrusive::member_hook< | ||
|  |                     context, detail::worker_hook, & context::worker_hook_ >, | ||
|  |                 intrusive::constant_time_size< false > >    worker_queue_t; | ||
|  | 
 | ||
|  |     std::unique_ptr< algo::algorithm >  algo_; | ||
|  |     context                         *   main_ctx_{ nullptr }; | ||
|  |     intrusive_ptr< context >            dispatcher_ctx_{}; | ||
|  |     // worker-queue contains all context' mananged by this scheduler
 | ||
|  |     // except main-context and dispatcher-context
 | ||
|  |     // unlink happens on destruction of a context
 | ||
|  |     worker_queue_t                      worker_queue_{}; | ||
|  |     // terminated-queue contains context' which have been terminated
 | ||
|  |     terminated_queue_t                  terminated_queue_{}; | ||
|  | #if ! defined(BOOST_FIBERS_NO_ATOMICS)
 | ||
|  |     // remote ready-queue contains context' signaled by schedulers
 | ||
|  |     // running in other threads
 | ||
|  |     detail::context_mpsc_queue          remote_ready_queue_{}; | ||
|  |     // sleep-queue contains context' which have been called
 | ||
|  | #endif
 | ||
|  |     // scheduler::wait_until()
 | ||
|  |     sleep_queue_t                       sleep_queue_{}; | ||
|  |     bool                                shutdown_{ false }; | ||
|  | 
 | ||
|  |     context * get_next_() noexcept; | ||
|  | 
 | ||
|  |     void release_terminated_() noexcept; | ||
|  | 
 | ||
|  | #if ! defined(BOOST_FIBERS_NO_ATOMICS)
 | ||
|  |     void remote_ready2ready_() noexcept; | ||
|  | #endif
 | ||
|  | 
 | ||
|  |     void sleep2ready_() noexcept; | ||
|  | 
 | ||
|  | public: | ||
|  |     scheduler() noexcept; | ||
|  | 
 | ||
|  |     scheduler( scheduler const&) = delete; | ||
|  |     scheduler & operator=( scheduler const&) = delete; | ||
|  | 
 | ||
|  |     virtual ~scheduler(); | ||
|  | 
 | ||
|  |     void set_ready( context *) noexcept; | ||
|  | 
 | ||
|  | #if ! defined(BOOST_FIBERS_NO_ATOMICS)
 | ||
|  |     void set_remote_ready( context *) noexcept; | ||
|  | #endif
 | ||
|  | 
 | ||
|  | #if (BOOST_EXECUTION_CONTEXT==1)
 | ||
|  |     void dispatch() noexcept; | ||
|  | 
 | ||
|  |     void set_terminated( context *) noexcept; | ||
|  | #else
 | ||
|  |     boost::context::execution_context< detail::data_t * > dispatch() noexcept; | ||
|  | 
 | ||
|  |     boost::context::execution_context< detail::data_t * > set_terminated( context *) noexcept; | ||
|  | #endif
 | ||
|  | 
 | ||
|  |     void yield( context *) noexcept; | ||
|  | 
 | ||
|  |     bool wait_until( context *, | ||
|  |                      std::chrono::steady_clock::time_point const&) noexcept; | ||
|  |     bool wait_until( context *, | ||
|  |                      std::chrono::steady_clock::time_point const&, | ||
|  |                      detail::spinlock_lock &) noexcept; | ||
|  | 
 | ||
|  |     void suspend() noexcept; | ||
|  |     void suspend( detail::spinlock_lock &) noexcept; | ||
|  | 
 | ||
|  |     bool has_ready_fibers() const noexcept; | ||
|  | 
 | ||
|  |     void set_algo( std::unique_ptr< algo::algorithm >) noexcept; | ||
|  | 
 | ||
|  |     void attach_main_context( context *) noexcept; | ||
|  | 
 | ||
|  |     void attach_dispatcher_context( intrusive_ptr< context >) noexcept; | ||
|  | 
 | ||
|  |     void attach_worker_context( context *) noexcept; | ||
|  | 
 | ||
|  |     void detach_worker_context( context *) noexcept; | ||
|  | }; | ||
|  | 
 | ||
|  | }} | ||
|  | 
 | ||
|  | #ifdef _MSC_VER
 | ||
|  | # pragma warning(pop)
 | ||
|  | #endif
 | ||
|  | 
 | ||
|  | #ifdef BOOST_HAS_ABI_HEADERS
 | ||
|  | #  include BOOST_ABI_SUFFIX
 | ||
|  | #endif
 | ||
|  | 
 | ||
|  | #endif // BOOST_FIBERS_FIBER_MANAGER_H
 |