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 executor_type
get_executor(int pri
= 0) noexcept
84 return executor_type(*const_cast<priority_scheduler
*>(this), pri
);
89 std::unique_lock
<std::mutex
> lock(mutex_
);
92 condition_
.wait(lock
, [&]{ return stopped_
|| !queue_
.empty(); });
105 std::lock_guard
<std::mutex
> lock(mutex_
);
107 condition_
.notify_all();
114 void (*execute_
)(std::shared_ptr
<item_base
>&);
117 template <class Func
>
118 struct item
: item_base
120 item(int pri
, Func f
) : function_(std::move(f
))
123 execute_
= [](std::shared_ptr
<item_base
>& p
)
125 Func
tmp(std::move(static_cast<item
*>(p
.get())->function_
));
137 const std::shared_ptr
<item_base
>& a
,
138 const std::shared_ptr
<item_base
>& b
)
140 return a
->priority_
< b
->priority_
;
145 std::condition_variable condition_
;
147 std::shared_ptr
<item_base
>,
148 std::vector
<std::shared_ptr
<item_base
>>,
150 bool stopped_
= false;
155 priority_scheduler sched
;
156 auto low
= sched
.get_executor(0);
157 auto med
= sched
.get_executor(1);
158 auto high
= sched
.get_executor(2);
159 dispatch(low
, []{ std::cout
<< "1\n"; });
160 dispatch(low
, []{ std::cout
<< "11\n"; });
161 dispatch(med
, []{ std::cout
<< "2\n"; });
162 dispatch(med
, []{ std::cout
<< "22\n"; });
163 dispatch(high
, []{ std::cout
<< "3\n"; });
164 dispatch(high
, []{ std::cout
<< "33\n"; });
165 dispatch(high
, []{ std::cout
<< "333\n"; });
166 dispatch(sched
.get_executor(-1), [&]{ sched
.stop(); });