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