Seastar
High performance C++ framework for concurrent servers
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Modules Pages
scheduling_specific.hh
1/*
2 * This file is open source software, licensed to you under the terms
3 * of the Apache License, Version 2.0 (the "License"). See the NOTICE file
4 * distributed with this work for additional information regarding copyright
5 * ownership. You may not use this file except in compliance with the License.
6 *
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing,
12 * software distributed under the License is distributed on an
13 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 * KIND, either express or implied. See the License for the
15 * specific language governing permissions and limitations
16 * under the License.
17 */
18/*
19 * Copyright (C) 2019 Scylla DB Ltd
20 */
21
22#ifndef SEASTAR_MODULE
24#include <seastar/core/map_reduce.hh>
25#include <seastar/util/modules.hh>
26#include <array>
27#include <map>
28#include <typeindex>
29#include <vector>
30#include <ranges>
31#endif
32
33#pragma once
34
35namespace seastar {
36
37namespace internal {
38
39struct scheduling_group_specific_thread_local_data {
40 struct per_scheduling_group {
41 bool queue_is_initialized = false;
47 std::vector<void*> specific_vals;
48 };
49 std::array<per_scheduling_group, max_scheduling_groups()> per_scheduling_group_data;
50 std::map<unsigned long, scheduling_group_key_config> scheduling_group_key_configs;
51};
52
53#ifdef SEASTAR_BUILD_SHARED_LIBS
54scheduling_group_specific_thread_local_data** get_scheduling_group_specific_thread_local_data_ptr() noexcept;
55#else
56inline
57scheduling_group_specific_thread_local_data** get_scheduling_group_specific_thread_local_data_ptr() noexcept {
58 static thread_local scheduling_group_specific_thread_local_data* data;
59 return &data;
60}
61#endif
62inline
63scheduling_group_specific_thread_local_data& get_scheduling_group_specific_thread_local_data() noexcept {
64 return **get_scheduling_group_specific_thread_local_data_ptr();
65}
66
67[[noreturn]] void no_such_scheduling_group(scheduling_group sg);
68
77template<typename T>
78T* scheduling_group_get_specific_ptr(scheduling_group sg, scheduling_group_key key) noexcept {
79 auto& data = internal::get_scheduling_group_specific_thread_local_data();
80#ifdef SEASTAR_DEBUG
81 assert(std::type_index(typeid(T)) == data.scheduling_group_key_configs[key.id()].type_index);
82#endif
83 auto sg_id = internal::scheduling_group_index(sg);
84 if (__builtin_expect(sg_id < data.per_scheduling_group_data.size() &&
85 data.per_scheduling_group_data[sg_id].queue_is_initialized, true)) {
86 return reinterpret_cast<T*>(data.per_scheduling_group_data[sg_id].specific_vals[key.id()]);
87 }
88 return nullptr;
89}
90
91}
92
93SEASTAR_MODULE_EXPORT_BEGIN
94
104template<typename T>
106 T* p = internal::scheduling_group_get_specific_ptr<T>(sg, std::move(key));
107 if (!p) {
108 internal::no_such_scheduling_group(sg);
109 }
110 return *p;
111}
112
120template<typename T>
122 // Unlike internal::scheduling_group_get_specific_ptr, this can
123 // return a reference to an element whose queue_is_initialized is
124 // false.
125 auto& data = internal::get_scheduling_group_specific_thread_local_data();
126 assert(std::type_index(typeid(T)) == data.scheduling_group_key_configs[key.id()].type_index);
127 auto sg_id = internal::scheduling_group_index(current_scheduling_group());
128 return *reinterpret_cast<T*>(data.per_scheduling_group_data[sg_id].specific_vals[key.id()]);
129}
130
146template<typename SpecificValType, typename Mapper, typename Reducer, typename Initial>
147requires requires(SpecificValType specific_val, Mapper mapper, Reducer reducer, Initial initial) {
148 {reducer(initial, mapper(specific_val))} -> std::convertible_to<Initial>;
149}
150future<typename function_traits<Reducer>::return_type>
151map_reduce_scheduling_group_specific(Mapper mapper, Reducer reducer,
152 Initial initial_val, scheduling_group_key key) {
153 using per_scheduling_group = internal::scheduling_group_specific_thread_local_data::per_scheduling_group;
154 auto& data = internal::get_scheduling_group_specific_thread_local_data();
155 auto wrapped_mapper = [key, mapper] (per_scheduling_group& psg) {
156 auto id = internal::scheduling_group_key_id(key);
157 return make_ready_future<typename function_traits<Mapper>::return_type>
158 (mapper(*reinterpret_cast<SpecificValType*>(psg.specific_vals[id])));
159 };
160
161 return map_reduce(
162 data.per_scheduling_group_data
163 | std::views::filter(std::mem_fn(&per_scheduling_group::queue_is_initialized)),
164 wrapped_mapper, std::move(initial_val), reducer);
165}
166
180template<typename SpecificValType, typename Reducer, typename Initial>
181requires requires(SpecificValType specific_val, Reducer reducer, Initial initial) {
182 {reducer(initial, specific_val)} -> std::convertible_to<Initial>;
183}
184future<typename function_traits<Reducer>::return_type>
185reduce_scheduling_group_specific(Reducer reducer, Initial initial_val, scheduling_group_key key) {
186 using per_scheduling_group = internal::scheduling_group_specific_thread_local_data::per_scheduling_group;
187 auto& data = internal::get_scheduling_group_specific_thread_local_data();
188
189 auto mapper = [key] (per_scheduling_group& psg) {
190 auto id = internal::scheduling_group_key_id(key);
191 return make_ready_future<SpecificValType>(*reinterpret_cast<SpecificValType*>(psg.specific_vals[id]));
192 };
193
194 return map_reduce(
195 data.per_scheduling_group_data
196 | std::views::filter(std::mem_fn(&per_scheduling_group::queue_is_initialized)),
197 mapper, std::move(initial_val), reducer);
198}
199
200SEASTAR_MODULE_EXPORT_END
201
202}
Definition: scheduling.hh:183
Identifies function calls that are accounted as a group.
Definition: scheduling.hh:285
auto map_reduce(Iterator begin, Iterator end, Mapper &&mapper, Reducer &&r) -> typename reducer_traits< Reducer >::future_type
Definition: map_reduce.hh:107
Seastar API namespace.
Definition: abort_on_ebadf.hh:26
future< typename function_traits< Reducer >::return_type > map_reduce_scheduling_group_specific(Mapper mapper, Reducer reducer, Initial initial_val, scheduling_group_key key)
Definition: scheduling_specific.hh:151
scheduling_group current_scheduling_group() noexcept
Returns the current scheduling group.
Definition: scheduling.hh:397
T & scheduling_group_get_specific(scheduling_group sg, scheduling_group_key key)
Definition: scheduling_specific.hh:105
future< typename function_traits< Reducer >::return_type > reduce_scheduling_group_specific(Reducer reducer, Initial initial_val, scheduling_group_key key)
Definition: scheduling_specific.hh:185