119 lines
		
	
	
		
			3.1 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
		
		
			
		
	
	
			119 lines
		
	
	
		
			3.1 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
|   | // Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
 | ||
|  | 
 | ||
|  | #pragma once
 | ||
|  | 
 | ||
|  | #if !defined(RXCPP_RX_SCHEDULER_EVENT_LOOP_HPP)
 | ||
|  | #define RXCPP_RX_SCHEDULER_EVENT_LOOP_HPP
 | ||
|  | 
 | ||
|  | #include "../rx-includes.hpp"
 | ||
|  | 
 | ||
|  | namespace rxcpp { | ||
|  | 
 | ||
|  | namespace schedulers { | ||
|  | 
 | ||
|  | struct event_loop : public scheduler_interface | ||
|  | { | ||
|  | private: | ||
|  |     typedef event_loop this_type; | ||
|  |     event_loop(const this_type&); | ||
|  | 
 | ||
|  |     struct loop_worker : public worker_interface | ||
|  |     { | ||
|  |     private: | ||
|  |         typedef loop_worker this_type; | ||
|  |         loop_worker(const this_type&); | ||
|  | 
 | ||
|  |         typedef detail::schedulable_queue< | ||
|  |             typename clock_type::time_point> queue_item_time; | ||
|  | 
 | ||
|  |         typedef queue_item_time::item_type item_type; | ||
|  | 
 | ||
|  |         composite_subscription lifetime; | ||
|  |         worker controller; | ||
|  |         std::shared_ptr<const scheduler_interface> alive; | ||
|  | 
 | ||
|  |     public: | ||
|  |         virtual ~loop_worker() | ||
|  |         { | ||
|  |         } | ||
|  |         loop_worker(composite_subscription cs, worker w, std::shared_ptr<const scheduler_interface> alive) | ||
|  |             : lifetime(cs) | ||
|  |             , controller(w) | ||
|  |             , alive(alive) | ||
|  |         { | ||
|  |             auto token = controller.add(cs); | ||
|  |             cs.add([token, w](){ | ||
|  |                 w.remove(token); | ||
|  |             }); | ||
|  |         } | ||
|  | 
 | ||
|  |         virtual clock_type::time_point now() const { | ||
|  |             return clock_type::now(); | ||
|  |         } | ||
|  | 
 | ||
|  |         virtual void schedule(const schedulable& scbl) const { | ||
|  |             controller.schedule(lifetime, scbl.get_action()); | ||
|  |         } | ||
|  | 
 | ||
|  |         virtual void schedule(clock_type::time_point when, const schedulable& scbl) const { | ||
|  |             controller.schedule(when, lifetime, scbl.get_action()); | ||
|  |         } | ||
|  |     }; | ||
|  | 
 | ||
|  |     mutable thread_factory factory; | ||
|  |     scheduler newthread; | ||
|  |     mutable std::atomic<std::size_t> count; | ||
|  |     composite_subscription loops_lifetime; | ||
|  |     std::vector<worker> loops; | ||
|  | 
 | ||
|  | public: | ||
|  |     event_loop() | ||
|  |         : factory([](std::function<void()> start){ | ||
|  |             return std::thread(std::move(start)); | ||
|  |         }) | ||
|  |         , newthread(make_new_thread()) | ||
|  |         , count(0) | ||
|  |     { | ||
|  |         auto remaining = std::max(std::thread::hardware_concurrency(), unsigned(4)); | ||
|  |         while (remaining--) { | ||
|  |             loops.push_back(newthread.create_worker(loops_lifetime)); | ||
|  |         } | ||
|  |     } | ||
|  |     explicit event_loop(thread_factory tf) | ||
|  |         : factory(tf) | ||
|  |         , newthread(make_new_thread(tf)) | ||
|  |         , count(0) | ||
|  |     { | ||
|  |         auto remaining = std::max(std::thread::hardware_concurrency(), unsigned(4)); | ||
|  |         while (remaining--) { | ||
|  |             loops.push_back(newthread.create_worker(loops_lifetime)); | ||
|  |         } | ||
|  |     } | ||
|  |     virtual ~event_loop() | ||
|  |     { | ||
|  |         loops_lifetime.unsubscribe(); | ||
|  |     } | ||
|  | 
 | ||
|  |     virtual clock_type::time_point now() const { | ||
|  |         return clock_type::now(); | ||
|  |     } | ||
|  | 
 | ||
|  |     virtual worker create_worker(composite_subscription cs) const { | ||
|  |         return worker(cs, std::make_shared<loop_worker>(cs, loops[++count % loops.size()], this->shared_from_this())); | ||
|  |     } | ||
|  | }; | ||
|  | 
 | ||
|  | inline scheduler make_event_loop() { | ||
|  |     static scheduler instance = make_scheduler<event_loop>(); | ||
|  |     return instance; | ||
|  | } | ||
|  | inline scheduler make_event_loop(thread_factory tf) { | ||
|  |     return make_scheduler<event_loop>(tf); | ||
|  | } | ||
|  | 
 | ||
|  | } | ||
|  | 
 | ||
|  | } | ||
|  | 
 | ||
|  | #endif
 |