diff options
Diffstat (limited to '3rdparty/asio/src/examples/cpp14/executors/priority_scheduler.cpp')
-rw-r--r-- | 3rdparty/asio/src/examples/cpp14/executors/priority_scheduler.cpp | 181 |
1 files changed, 181 insertions, 0 deletions
diff --git a/3rdparty/asio/src/examples/cpp14/executors/priority_scheduler.cpp b/3rdparty/asio/src/examples/cpp14/executors/priority_scheduler.cpp new file mode 100644 index 00000000000..da4caf0d0ef --- /dev/null +++ b/3rdparty/asio/src/examples/cpp14/executors/priority_scheduler.cpp @@ -0,0 +1,181 @@ +#include <asio/execution.hpp> +#include <condition_variable> +#include <iostream> +#include <memory> +#include <mutex> +#include <queue> + +namespace execution = asio::execution; + +namespace custom_props { + + struct priority + { + template <typename T> + static constexpr bool is_applicable_property_v = + execution::is_executor<T>::value; + + static constexpr bool is_requirable = true; + static constexpr bool is_preferable = true; + + using polymorphic_query_result_type = int; + + int value() const { return value_; } + + int value_ = 1; + }; + + constexpr priority low_priority{0}; + constexpr priority normal_priority{1}; + constexpr priority high_priority{2}; + +} // namespace custom_props + +class priority_scheduler +{ +public: + // A class that satisfies the Executor requirements. + class executor_type + { + public: + executor_type(priority_scheduler& ctx) noexcept + : context_(ctx), priority_(custom_props::normal_priority.value()) + { + } + + priority_scheduler& query(execution::context_t) const noexcept + { + return context_; + } + + int query(custom_props::priority) const noexcept + { + return priority_; + } + + executor_type require(custom_props::priority pri) const + { + executor_type new_ex(*this); + new_ex.priority_ = pri.value(); + return new_ex; + } + + template <class Func> + void execute(Func f) const + { + auto p(std::make_shared<item<Func>>(priority_, std::move(f))); + std::lock_guard<std::mutex> lock(context_.mutex_); + context_.queue_.push(p); + context_.condition_.notify_one(); + } + + friend bool operator==(const executor_type& a, + const executor_type& b) noexcept + { + return &a.context_ == &b.context_; + } + + friend bool operator!=(const executor_type& a, + const executor_type& b) noexcept + { + return &a.context_ != &b.context_; + } + + private: + priority_scheduler& context_; + int priority_; + }; + + executor_type executor() noexcept + { + return executor_type(*const_cast<priority_scheduler*>(this)); + } + + void run() + { + std::unique_lock<std::mutex> lock(mutex_); + for (;;) + { + condition_.wait(lock, [&]{ return stopped_ || !queue_.empty(); }); + if (stopped_) + return; + auto p(queue_.top()); + queue_.pop(); + lock.unlock(); + p->execute_(p); + lock.lock(); + } + } + + void stop() + { + std::lock_guard<std::mutex> lock(mutex_); + stopped_ = true; + condition_.notify_all(); + } + +private: + struct item_base + { + int priority_; + void (*execute_)(std::shared_ptr<item_base>&); + }; + + template <class Func> + struct item : item_base + { + item(int pri, Func f) : function_(std::move(f)) + { + priority_ = pri; + execute_ = [](std::shared_ptr<item_base>& p) + { + Func tmp(std::move(static_cast<item*>(p.get())->function_)); + p.reset(); + tmp(); + }; + } + + Func function_; + }; + + struct item_comp + { + bool operator()( + const std::shared_ptr<item_base>& a, + const std::shared_ptr<item_base>& b) + { + return a->priority_ < b->priority_; + } + }; + + std::mutex mutex_; + std::condition_variable condition_; + std::priority_queue< + std::shared_ptr<item_base>, + std::vector<std::shared_ptr<item_base>>, + item_comp> queue_; + bool stopped_ = false; +}; + +int main() +{ + priority_scheduler sched; + auto ex = sched.executor(); + auto prefer_low = asio::prefer(ex, custom_props::low_priority); + auto low = asio::require(ex, custom_props::low_priority); + auto med = asio::require(ex, custom_props::normal_priority); + auto high = asio::require(ex, custom_props::high_priority); + execution::any_executor<custom_props::priority> poly_high(high); + execution::execute(prefer_low, []{ std::cout << "1\n"; }); + execution::execute(low, []{ std::cout << "11\n"; }); + execution::execute(low, []{ std::cout << "111\n"; }); + execution::execute(med, []{ std::cout << "2\n"; }); + execution::execute(med, []{ std::cout << "22\n"; }); + execution::execute(high, []{ std::cout << "3\n"; }); + execution::execute(high, []{ std::cout << "33\n"; }); + execution::execute(high, []{ std::cout << "333\n"; }); + execution::execute(poly_high, []{ std::cout << "3333\n"; }); + execution::execute(asio::require(ex, custom_props::priority{-1}), [&]{ sched.stop(); }); + sched.run(); + std::cout << "polymorphic query result = " << asio::query(poly_high, custom_props::priority{}) << "\n"; +} |