/* * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License Version 2.0 with LLVM Exceptions * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * https://llvm.org/LICENSE.txt * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include #include #include #include #include #include #include #include #include #include #include #include using namespace unifex; using namespace std::chrono_literals; namespace { class delegating_scheduler; class delegating_context { public: delegating_context(int capacity) : capacity_{capacity} {} bool reserve() { auto lck = std::scoped_lock{m_}; bool reservation_made = reservation_count_ < capacity_; if(reservation_made) { ++reservation_count_; } return reservation_made; } int get_count() { return run_count_; } void run() { run_count_++; } delegating_scheduler get_scheduler() noexcept; private: friend class delegating_sender; std::mutex m_; int reservation_count_{0}; std::atomic run_count_{0}; int capacity_; timed_single_thread_context single_thread_context_; }; template struct FuncWrapper { T func_; operator std::invoke_result_t() { return func_(); } }; template class delegating_operation final { public: template delegating_operation(InitFunc&& func, delegating_context* context) : op_{ std::in_place_type_t>{}, FuncWrapper{std::forward(func)}}, context_{context} { } inline void start() noexcept { if(std::holds_alternative(op_)) { // Start a delegated operation std::get(op_).start(); } else { // Start immediately on the local context context_->run(); std::get(op_).start();; } } std::variant op_; delegating_context* context_ = nullptr; }; class delegating_sender { public: template < template class Variant, template class Tuple> using value_types = Variant>; template