1 #include <boost/asio/dispatch.hpp>
2 #include <boost/asio/execution_context.hpp>
3 #include <condition_variable>
9 using boost::asio::dispatch
;
10 using boost::asio::execution_context
;
12 class priority_scheduler
: public execution_context
15 // A class that satisfies the Executor requirements.
19 executor_type(priority_scheduler
& ctx
, int pri
) noexcept
20 : context_(ctx
), priority_(pri
)
24 priority_scheduler
& context() const noexcept
29 void on_work_started() const noexcept
31 // This executor doesn't count work. Instead, the scheduler simply runs
32 // until explicitly stopped.
35 void on_work_finished() const noexcept
37 // This executor doesn't count work. Instead, the scheduler simply runs
38 // until explicitly stopped.
41 template <class Func
, class Alloc
>
42 void dispatch(Func
&& f
, const Alloc
& a
) const
44 post(std::forward
<Func
>(f
), a
);
47 template <class Func
, class Alloc
>
48 void post(Func f
, const Alloc
& a
) const
50 auto p(std::allocate_shared
<item
<Func
>>(
51 typename
std::allocator_traits
<
52 Alloc
>::template rebind_alloc
<char>(a
),
53 priority_
, std::move(f
)));
54 std::lock_guard
<std::mutex
> lock(context_
.mutex_
);
55 context_
.queue_
.push(p
);
56 context_
.condition_
.notify_one();
59 template <class Func
, class Alloc
>
60 void defer(Func
&& f
, const Alloc
& a
) const
62 post(std::forward
<Func
>(f
), a
);
65 friend bool operator==(const executor_type
& a
,
66 const executor_type
& b
) noexcept
68 return &a
.context_
== &b
.context_
;
71 friend bool operator!=(const executor_type
& a
,
72 const executor_type
& b
) noexcept
74 return &a
.context_
!= &b
.context_
;
78 priority_scheduler
& context_
;
82 ~priority_scheduler() noexcept
88 executor_type
get_executor(int pri
= 0) noexcept
90 return executor_type(*const_cast<priority_scheduler
*>(this), pri
);
95 std::unique_lock
<std::mutex
> lock(mutex_
);
98 condition_
.wait(lock
, [&]{ return stopped_
|| !queue_
.empty(); });
101 auto p(queue_
.top());
111 std::lock_guard
<std::mutex
> lock(mutex_
);
113 condition_
.notify_all();
120 void (*execute_
)(std::shared_ptr
<item_base
>&);
123 template <class Func
>
124 struct item
: item_base
126 item(int pri
, Func f
) : function_(std::move(f
))
129 execute_
= [](std::shared_ptr
<item_base
>& p
)
131 Func
tmp(std::move(static_cast<item
*>(p
.get())->function_
));
143 const std::shared_ptr
<item_base
>& a
,
144 const std::shared_ptr
<item_base
>& b
)
146 return a
->priority_
< b
->priority_
;
151 std::condition_variable condition_
;
153 std::shared_ptr
<item_base
>,
154 std::vector
<std::shared_ptr
<item_base
>>,
156 bool stopped_
= false;
161 priority_scheduler sched
;
162 auto low
= sched
.get_executor(0);
163 auto med
= sched
.get_executor(1);
164 auto high
= sched
.get_executor(2);
165 dispatch(low
, []{ std::cout
<< "1\n"; });
166 dispatch(low
, []{ std::cout
<< "11\n"; });
167 dispatch(med
, []{ std::cout
<< "2\n"; });
168 dispatch(med
, []{ std::cout
<< "22\n"; });
169 dispatch(high
, []{ std::cout
<< "3\n"; });
170 dispatch(high
, []{ std::cout
<< "33\n"; });
171 dispatch(high
, []{ std::cout
<< "333\n"; });
172 dispatch(sched
.get_executor(-1), [&]{ sched
.stop(); });