1 // license:GPL-2.0+
2 // copyright-holders:Couriersud
3 
4 ///
5 /// \file queue.h
6 ///
7 
8 #ifndef NL_CORE_QUEUE_H_
9 #define NL_CORE_QUEUE_H_
10 
11 #include "queue.h"
12 
13 #include "../nl_errstr.h"
14 #include "../nltypes.h"
15 
16 #include "../plib/pstate.h"
17 #include "../plib/pstring.h"
18 #include "../plib/ptimed_queue.h"
19 
20 #include <array>
21 #include <unordered_map>
22 #include <utility>
23 #include <vector>
24 #include <queue>
25 
26 namespace netlist
27 {
28 	namespace detail {
29 		// Use timed_queue_heap to use stdc++ heap functions instead of linear processing.
30 		// This slows down processing by about 35% on a Kaby Lake.
31 		// template <class T, bool TS>
32 		// using timed_queue = plib::timed_queue_heap<T, TS>;
33 
34 		template <class T, bool TS>
35 		using timed_queue = plib::timed_queue_linear<T, TS>;
36 
37 		// -----------------------------------------------------------------------------
38 		// queue_t
39 		// -----------------------------------------------------------------------------
40 
41 		// We don't need a thread-safe queue currently. Parallel processing of
42 		// solvers will update inputs after parallel processing.
43 
44 		template <typename O, bool TS>
45 		class queue_base :
46 				public timed_queue<plib::pqentry_t<netlist_time_ext, O *>, false>,
47 				public plib::state_manager_t::callback_t
48 		{
49 		public:
50 			using entry_t = plib::pqentry_t<netlist_time_ext, O *>;
51 			using base_queue = timed_queue<entry_t, false>;
52 			using id_delegate = plib::pmfp<std::size_t, const O *>;
53 			using obj_delegate = plib::pmfp<O *, std::size_t>;
54 
queue_base(std::size_t size,id_delegate get_id,obj_delegate get_obj)55 			explicit queue_base(std::size_t size, id_delegate get_id, obj_delegate get_obj)
56 			: timed_queue<plib::pqentry_t<netlist_time_ext, O *>, false>(size)
57 			, m_qsize(0)
58 			, m_times(size)
59 			, m_net_ids(size)
60 			, m_get_id(get_id)
61 			, m_obj_by_id(get_obj)
62 			{
63 			}
64 
65 			~queue_base() noexcept override = default;
66 
67 			queue_base(const queue_base &) = delete;
68 			queue_base(queue_base &&) = delete;
69 			queue_base &operator=(const queue_base &) = delete;
70 			queue_base &operator=(queue_base &&) = delete;
71 
72 		protected:
73 
register_state(plib::state_manager_t & manager,const pstring & module)74 			void register_state(plib::state_manager_t &manager, const pstring &module) override
75 			{
76 				manager.save_item(this, m_qsize, module + "." + "qsize");
77 				manager.save_item(this, &m_times[0], module + "." + "times", m_times.size());
78 				manager.save_item(this, &m_net_ids[0], module + "." + "names", m_net_ids.size());
79 			}
on_pre_save(plib::state_manager_t & manager)80 			void on_pre_save(plib::state_manager_t &manager) override
81 			{
82 				plib::unused_var(manager);
83 				m_qsize = this->size();
84 				for (std::size_t i = 0; i < m_qsize; i++ )
85 				{
86 					m_times[i] =  this->listptr()[i].exec_time().as_raw();
87 					m_net_ids[i] = m_get_id(this->listptr()[i].object());
88 				}
89 			}
on_post_load(plib::state_manager_t & manager)90 			void on_post_load(plib::state_manager_t &manager) override
91 			{
92 				plib::unused_var(manager);
93 				this->clear();
94 				for (std::size_t i = 0; i < m_qsize; i++ )
95 				{
96 					O *n = m_obj_by_id(m_net_ids[i]);
97 					this->template push<false>(entry_t(netlist_time_ext::from_raw(m_times[i]),n));
98 				}
99 			}
100 
101 		private:
102 			std::size_t m_qsize;
103 			std::vector<netlist_time_ext::internal_type> m_times;
104 			std::vector<std::size_t> m_net_ids;
105 			id_delegate m_get_id;
106 			obj_delegate m_obj_by_id;
107 		};
108 
109 		using queue_t = queue_base<net_t, false>;
110 
111 	} // namespace detail
112 } // namespace netlist
113 
114 
115 #endif // NL_CORE_QUEUE_H_
116