Wire Sysio Wire Sysion 1.0.0
Loading...
Searching...
No Matches
execution_priority_queue.hpp
Go to the documentation of this file.
1#pragma once
2#include <boost/asio.hpp>
3
4#include <queue>
5
6namespace appbase {
7// adapted from: https://www.boost.org/doc/libs/1_69_0/doc/html/boost_asio/example/cpp11/invocation/prioritised_handlers.cpp
8
9struct priority {
10 static constexpr int lowest = std::numeric_limits<int>::min();
11 static constexpr int low = 10;
12 static constexpr int medium_low = 25;
13 static constexpr int medium = 50;
14 static constexpr int medium_high = 75;
15 static constexpr int high = 100;
16 static constexpr int highest = std::numeric_limits<int>::max();
17};
18
19class execution_priority_queue : public boost::asio::execution_context
20{
21public:
22
23 template <typename Function>
24 void add(int priority, Function function)
25 {
26 std::unique_ptr<queued_handler_base> handler(new queued_handler<Function>(priority, --order_, std::move(function)));
27
28 handlers_.push(std::move(handler));
29 }
30
32 {
33 while (!handlers_.empty()) {
34 handlers_.top()->execute();
35 handlers_.pop();
36 }
37 }
38
40 {
41 if( !handlers_.empty() ) {
42 handlers_.top()->execute();
43 handlers_.pop();
44 }
45
46 return !handlers_.empty();
47 }
48
49 size_t size() { return handlers_.size(); }
50
52 {
53 public:
55 : context_(q), priority_(p)
56 {
57 }
58
60 {
61 return context_;
62 }
63
64 template <typename Function, typename Allocator>
65 void dispatch(Function f, const Allocator&) const
66 {
67 context_.add(priority_, std::move(f));
68 }
69
70 template <typename Function, typename Allocator>
71 void post(Function f, const Allocator&) const
72 {
73 context_.add(priority_, std::move(f));
74 }
75
76 template <typename Function, typename Allocator>
77 void defer(Function f, const Allocator&) const
78 {
79 context_.add(priority_, std::move(f));
80 }
81
82 void on_work_started() const noexcept {}
83 void on_work_finished() const noexcept {}
84
85 bool operator==(const executor& other) const noexcept
86 {
87 return &context_ == &other.context_ && priority_ == other.priority_;
88 }
89
90 bool operator!=(const executor& other) const noexcept
91 {
92 return !operator==(other);
93 }
94
95 private:
97 int priority_;
98 };
99
100 template <typename Function>
101 boost::asio::executor_binder<Function, executor>
102 wrap(int priority, Function&& func)
103 {
104 return boost::asio::bind_executor( executor(*this, priority), std::forward<Function>(func) );
105 }
106
107private:
108 class queued_handler_base
109 {
110 public:
111 queued_handler_base( int p, size_t order )
112 : priority_( p )
113 , order_( order )
114 {
115 }
116
117 virtual ~queued_handler_base() = default;
118
119 virtual void execute() = 0;
120
121 int priority() const { return priority_; }
122 // C++20
123 // friend std::weak_ordering operator<=>(const queued_handler_base&,
124 // const queued_handler_base&) noexcept = default;
125 friend bool operator<(const queued_handler_base& a,
126 const queued_handler_base& b) noexcept
127 {
128 return std::tie( a.priority_, a.order_ ) < std::tie( b.priority_, b.order_ );
129 }
130
131 private:
132 int priority_;
133 size_t order_;
134 };
135
136 template <typename Function>
137 class queued_handler : public queued_handler_base
138 {
139 public:
140 queued_handler(int p, size_t order, Function f)
141 : queued_handler_base( p, order )
142 , function_( std::move(f) )
143 {
144 }
145
146 void execute() override
147 {
148 function_();
149 }
150
151 private:
152 Function function_;
153 };
154
155 struct deref_less
156 {
157 template<typename Pointer>
158 bool operator()(const Pointer& a, const Pointer& b) noexcept(noexcept(*a < *b))
159 {
160 return *a < *b;
161 }
162 };
163
164 std::priority_queue<std::unique_ptr<queued_handler_base>, std::deque<std::unique_ptr<queued_handler_base>>, deref_less> handlers_;
165 std::size_t order_ = std::numeric_limits<size_t>::max(); // to maintain FIFO ordering in queue within priority
166};
167
168} // appbase
const mie::Vuint & p
Definition bn.cpp:27
Represents a JSON Pointer. Use Pointer for UTF8 encoding and default allocator.
Definition pointer.h:79
bool operator!=(const executor &other) const noexcept
execution_priority_queue & context() const noexcept
bool operator==(const executor &other) const noexcept
void post(Function f, const Allocator &) const
void dispatch(Function f, const Allocator &) const
void defer(Function f, const Allocator &) const
void add(int priority, Function function)
boost::asio::executor_binder< Function, executor > wrap(int priority, Function &&func)
Concept for allocating, resizing and freeing memory block.
Definition name.hpp:106
@ Function
Definition types.hpp:22
const GenericPointer< typename T::ValueType > T2 T::AllocatorType & a
Definition pointer.h:1181
static constexpr int medium_high
static constexpr int lowest
static constexpr int medium
static constexpr int medium_low
static constexpr int high
static constexpr int highest