1*c4568449SPavel Kumbrasev /* 2*c4568449SPavel Kumbrasev Copyright (c) 2022-2023 Intel Corporation 3*c4568449SPavel Kumbrasev 4*c4568449SPavel Kumbrasev Licensed under the Apache License, Version 2.0 (the "License"); 5*c4568449SPavel Kumbrasev you may not use this file except in compliance with the License. 6*c4568449SPavel Kumbrasev You may obtain a copy of the License at 7*c4568449SPavel Kumbrasev 8*c4568449SPavel Kumbrasev http://www.apache.org/licenses/LICENSE-2.0 9*c4568449SPavel Kumbrasev 10*c4568449SPavel Kumbrasev Unless required by applicable law or agreed to in writing, software 11*c4568449SPavel Kumbrasev distributed under the License is distributed on an "AS IS" BASIS, 12*c4568449SPavel Kumbrasev WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13*c4568449SPavel Kumbrasev See the License for the specific language governing permissions and 14*c4568449SPavel Kumbrasev limitations under the License. 15*c4568449SPavel Kumbrasev */ 16*c4568449SPavel Kumbrasev 17*c4568449SPavel Kumbrasev #ifndef _TBB_thread_serializer_handlers_H 18*c4568449SPavel Kumbrasev #define _TBB_thread_serializer_handlers_H 19*c4568449SPavel Kumbrasev 20*c4568449SPavel Kumbrasev #include "oneapi/tbb/mutex.h" 21*c4568449SPavel Kumbrasev #include "oneapi/tbb/rw_mutex.h" 22*c4568449SPavel Kumbrasev 23*c4568449SPavel Kumbrasev #include "thread_dispatcher.h" 24*c4568449SPavel Kumbrasev 25*c4568449SPavel Kumbrasev namespace tbb { 26*c4568449SPavel Kumbrasev namespace detail { 27*c4568449SPavel Kumbrasev namespace r1 { 28*c4568449SPavel Kumbrasev 29*c4568449SPavel Kumbrasev class thread_request_observer { 30*c4568449SPavel Kumbrasev protected: ~thread_request_observer()31*c4568449SPavel Kumbrasev virtual ~thread_request_observer() {} 32*c4568449SPavel Kumbrasev public: 33*c4568449SPavel Kumbrasev virtual void update(int delta) = 0; 34*c4568449SPavel Kumbrasev }; 35*c4568449SPavel Kumbrasev 36*c4568449SPavel Kumbrasev 37*c4568449SPavel Kumbrasev class thread_request_serializer : public thread_request_observer { 38*c4568449SPavel Kumbrasev using mutex_type = d1::mutex; 39*c4568449SPavel Kumbrasev public: 40*c4568449SPavel Kumbrasev thread_request_serializer(thread_dispatcher& td, int soft_limit); 41*c4568449SPavel Kumbrasev void set_active_num_workers(int soft_limit); is_no_workers_avaliable()42*c4568449SPavel Kumbrasev bool is_no_workers_avaliable() { return my_soft_limit == 0; } 43*c4568449SPavel Kumbrasev 44*c4568449SPavel Kumbrasev private: 45*c4568449SPavel Kumbrasev friend class thread_request_serializer_proxy; 46*c4568449SPavel Kumbrasev void update(int delta) override; 47*c4568449SPavel Kumbrasev static int limit_delta(int delta, int limit, int new_value); 48*c4568449SPavel Kumbrasev 49*c4568449SPavel Kumbrasev thread_dispatcher& my_thread_dispatcher; 50*c4568449SPavel Kumbrasev int my_soft_limit{ 0 }; 51*c4568449SPavel Kumbrasev int my_total_request{ 0 }; 52*c4568449SPavel Kumbrasev // my_pending_delta is set to pending_delta_base to have ability to hold negative values 53*c4568449SPavel Kumbrasev // consider increase base since thead number will be bigger than 1 << 15 54*c4568449SPavel Kumbrasev static constexpr std::uint64_t pending_delta_base = 1 << 15; 55*c4568449SPavel Kumbrasev std::atomic<std::uint64_t> my_pending_delta{ pending_delta_base }; 56*c4568449SPavel Kumbrasev mutex_type my_mutex; 57*c4568449SPavel Kumbrasev }; 58*c4568449SPavel Kumbrasev 59*c4568449SPavel Kumbrasev // Handles mandatory concurrency i.e. enables worker threads for enqueue tasks 60*c4568449SPavel Kumbrasev class thread_request_serializer_proxy : public thread_request_observer { 61*c4568449SPavel Kumbrasev using mutex_type = d1::rw_mutex; 62*c4568449SPavel Kumbrasev public: 63*c4568449SPavel Kumbrasev thread_request_serializer_proxy(thread_dispatcher& td, int soft_limit); 64*c4568449SPavel Kumbrasev void register_mandatory_request(int mandatory_delta); 65*c4568449SPavel Kumbrasev void set_active_num_workers(int soft_limit); 66*c4568449SPavel Kumbrasev 67*c4568449SPavel Kumbrasev private: 68*c4568449SPavel Kumbrasev void update(int delta) override; 69*c4568449SPavel Kumbrasev void enable_mandatory_concurrency(mutex_type::scoped_lock& lock); 70*c4568449SPavel Kumbrasev void disable_mandatory_concurrency(mutex_type::scoped_lock& lock); 71*c4568449SPavel Kumbrasev 72*c4568449SPavel Kumbrasev std::atomic<int> my_num_mandatory_requests{0}; 73*c4568449SPavel Kumbrasev bool my_is_mandatory_concurrency_enabled{false}; 74*c4568449SPavel Kumbrasev thread_request_serializer my_serializer; 75*c4568449SPavel Kumbrasev mutex_type my_mutex; 76*c4568449SPavel Kumbrasev }; 77*c4568449SPavel Kumbrasev 78*c4568449SPavel Kumbrasev } // namespace r1 79*c4568449SPavel Kumbrasev } // namespace detail 80*c4568449SPavel Kumbrasev } // namespace tbb 81*c4568449SPavel Kumbrasev 82*c4568449SPavel Kumbrasev #endif // _TBB_thread_serializer_handlers_H 83