DPC++ Runtime
Runtime libraries for oneAPI DPC++
properties.hpp
Go to the documentation of this file.
1 //==---------- properties.hpp --- SYCL extended property list --------------==//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #pragma once
10 
12 #include <sycl/ext/oneapi/properties/property.hpp> // for IsRuntimePr...
13 #include <sycl/ext/oneapi/properties/property_utils.hpp> // for Sorted, Mer...
14 #include <sycl/ext/oneapi/properties/property_value.hpp> // for property_value
15 
16 #include <tuple> // for tuple, tupl...
17 #include <type_traits> // for enable_if_t
18 #include <variant> // for tuple
19 
20 namespace sycl {
21 inline namespace _V1 {
22 namespace ext::oneapi::experimental {
23 
24 namespace detail {
25 
26 // Checks if a tuple of properties contains a property.
27 template <typename PropT, typename PropertiesT>
28 struct ContainsProperty : std::false_type {};
29 template <typename PropT, typename T, typename... Ts>
30 struct ContainsProperty<PropT, std::tuple<T, Ts...>>
31  : ContainsProperty<PropT, std::tuple<Ts...>> {};
32 template <typename PropT, typename... Rest>
33 struct ContainsProperty<PropT, std::tuple<PropT, Rest...>> : std::true_type {};
34 template <typename PropT, typename... PropValuesTs, typename... Rest>
36  PropT, std::tuple<property_value<PropT, PropValuesTs...>, Rest...>>
37  : std::true_type {};
38 
39 // Finds the full property_value type of a property in a tuple of properties.
40 // type is void if the type was not found in the tuple of properties.
41 template <typename CTPropertyT, typename PropertiesT = void>
43  using type = void;
44 };
45 template <typename CTPropertyT, typename OtherProperty, typename... Rest>
47  std::tuple<OtherProperty, Rest...>> {
48  using type =
49  typename FindCompileTimePropertyValueType<CTPropertyT,
50  std::tuple<Rest...>>::type;
51 };
52 template <typename CTPropertyT, typename... CTPropertyValueTs, typename... Rest>
54  CTPropertyT,
55  std::tuple<property_value<CTPropertyT, CTPropertyValueTs...>, Rest...>> {
56  using type = property_value<CTPropertyT, CTPropertyValueTs...>;
57 };
58 
59 template <typename CTPropertyT, bool HasProperty, typename PropertiesT = void>
60 static constexpr std::enable_if_t<
64  return {};
65 }
66 
67 template <typename CTPropertyT, bool HasProperty, typename PropertiesT = void>
68 static constexpr std::enable_if_t<!HasProperty, void> get_property() {
69  return;
70 }
71 
72 // Filters for all runtime properties with data in a tuple of properties.
73 // NOTE: We only need storage for runtime properties with data.
74 template <typename T> struct RuntimePropertyStorage {};
75 template <typename... Ts> struct RuntimePropertyStorage<std::tuple<Ts...>> {
76  using type = std::tuple<>;
77 };
78 template <typename T, typename... Ts>
79 struct RuntimePropertyStorage<std::tuple<T, Ts...>>
80  : std::conditional_t<IsRuntimeProperty<T>::value,
81  PrependTuple<T, typename RuntimePropertyStorage<
82  std::tuple<Ts...>>::type>,
83  RuntimePropertyStorage<std::tuple<Ts...>>> {};
84 
85 // Count occurrences of a type in a tuple.
86 template <typename T, typename Tuple> struct CountTypeInTuple;
87 template <typename T, typename... TupleTs>
88 struct CountTypeInTuple<T, std::tuple<TupleTs...>>
89  : std::integral_constant<
90  size_t, (0 + ... + static_cast<size_t>(std::is_same_v<T, TupleTs>))> {
91 };
92 
93 // Helper for counting the number of properties that are also in PropertyArgsT.
94 template <typename PropertyArgsT, typename Props> struct CountContainedProps;
95 template <typename PropertyArgsT>
96 struct CountContainedProps<PropertyArgsT, std::tuple<>>
97  : std::integral_constant<size_t, 0> {};
98 template <typename PropertyArgsT, typename PropertyT, typename... PropertyTs>
99 struct CountContainedProps<PropertyArgsT,
100  std::tuple<PropertyT, PropertyTs...>> {
101  static constexpr size_t NumOccurrences =
103  static_assert(NumOccurrences <= 1,
104  "Duplicate occurrences of property in constructor arguments.");
105  static constexpr size_t value =
106  CountContainedProps<PropertyArgsT, std::tuple<PropertyTs...>>::value +
107  NumOccurrences;
108 };
109 
110 // Helper class to extract a subset of elements from a tuple.
111 // NOTES: This assumes no duplicate properties and that all properties in the
112 // struct template argument appear in the tuple passed to Extract.
113 template <typename PropertyArgsT, typename PropertiesT>
115 template <typename PropertyArgsT>
116 struct ExtractProperties<PropertyArgsT, std::tuple<>> {
117  static constexpr std::tuple<> Extract(const PropertyArgsT &) {
118  return std::tuple<>{};
119  }
120 };
121 template <typename PropertyArgsT, typename PropertyT, typename... PropertiesTs>
122 struct ExtractProperties<PropertyArgsT,
123  std::tuple<PropertyT, PropertiesTs...>> {
124  static constexpr std::tuple<PropertyT, PropertiesTs...>
125  Extract(const PropertyArgsT &PropertyValues) {
126  // TODO: NumOccurrences and checks should be moved out of the function once
127  // https://github.com/intel/llvm/issues/13677 has been fixed.
128  constexpr size_t NumOccurrences =
130  static_assert(
131  NumOccurrences <= 1,
132  "Duplicate occurrences of property in constructor arguments.");
133  static_assert(NumOccurrences == 1 ||
134  std::is_default_constructible_v<PropertyT>,
135  "Each property in the property list must either be given an "
136  "argument in the constructor or be default-constructible.");
137 
138  auto NextExtractedProperties =
139  ExtractProperties<PropertyArgsT, std::tuple<PropertiesTs...>>::Extract(
140  PropertyValues);
141 
142  if constexpr (NumOccurrences == 1) {
143  return std::tuple_cat(
144  std::tuple<PropertyT>{std::get<PropertyT>(PropertyValues)},
145  NextExtractedProperties);
146  } else {
147  return std::tuple_cat(std::tuple<PropertyT>{PropertyT{}},
148  NextExtractedProperties);
149  }
150  }
151 };
152 
153 } // namespace detail
154 
155 template <typename PropertiesT> class properties {
157  "Properties must be in a tuple.");
159  "Unrecognized property in property list.");
161  "Properties in property list are not sorted.");
162  static_assert(detail::SortedAllUnique<PropertiesT>::value,
163  "Duplicate properties in property list.");
164  static_assert(detail::NoConflictingProperties<PropertiesT>::value,
165  "Conflicting properties in property list.");
166 
167 public:
168  template <typename... PropertyValueTs,
169  std::enable_if_t<detail::AllPropertyValues<
170  std::tuple<PropertyValueTs...>>::value,
171  int> = 0>
172  constexpr properties(PropertyValueTs... props)
173  : Storage(detail::ExtractProperties<std::tuple<PropertyValueTs...>,
174  StorageT>::Extract({props...})) {
175  // Default-constructible properties do not need to be in the arguments.
176  // For properties with a storage, default-constructibility is checked in
177  // ExtractProperties, while those without are so by default. As such, all
178  // arguments must be a unique property type and must be in PropertiesT.
179  constexpr size_t NumContainedProps =
180  detail::CountContainedProps<std::tuple<PropertyValueTs...>,
181  PropertiesT>::value;
182  static_assert(NumContainedProps == sizeof...(PropertyValueTs),
183  "One or more property argument is not a property in the "
184  "property list.");
185  }
186 
187  template <typename PropertyT>
188  static constexpr std::enable_if_t<detail::IsProperty<PropertyT>::value, bool>
191  }
192 
193  template <typename PropertyT>
194  typename std::enable_if_t<detail::IsRuntimeProperty<PropertyT>::value &&
195  has_property<PropertyT>(),
196  PropertyT>
197  get_property() const {
198  return std::get<PropertyT>(Storage);
199  }
200 
201  template <typename PropertyT>
202  typename std::enable_if_t<detail::IsRuntimeProperty<PropertyT>::value &&
203  !has_property<PropertyT>(),
204  void>
205  get_property() const {
206  static_assert(has_property<PropertyT>(),
207  "Property list does not contain the requested property.");
208  return;
209  }
210 
211  template <typename PropertyT>
212  static constexpr auto get_property(
213  typename std::enable_if_t<detail::IsCompileTimeProperty<PropertyT>::value>
214  * = 0) {
215  static_assert(has_property<PropertyT>(),
216  "Property list does not contain the requested property.");
217  return detail::get_property<PropertyT, has_property<PropertyT>(),
218  PropertiesT>();
219  }
220 
221 private:
222  using StorageT = typename detail::RuntimePropertyStorage<PropertiesT>::type;
223 
224  StorageT Storage;
225 };
226 
227 #ifdef __cpp_deduction_guides
228 // Deduction guides
229 template <typename... PropertyValueTs>
230 properties(PropertyValueTs... props)
231  -> properties<typename detail::Sorted<PropertyValueTs...>::type>;
232 #endif
233 
235 
236 // Property list traits
237 template <typename propertiesT> struct is_property_list : std::false_type {};
238 template <typename... PropertyValueTs>
239 struct is_property_list<properties<std::tuple<PropertyValueTs...>>>
240  : std::is_same<
241  properties<std::tuple<PropertyValueTs...>>,
242  properties<typename detail::Sorted<PropertyValueTs...>::type>> {};
243 
244 #if __cplusplus > 201402L
245 template <typename propertiesT>
247 #endif
248 
249 namespace detail {
250 
251 // Helper for reconstructing a properties type. This assumes that
252 // PropertyValueTs is sorted and contains only valid properties.
253 template <typename... PropertyValueTs>
254 using properties_t = properties<std::tuple<PropertyValueTs...>>;
255 
256 // Helper for merging two property lists;
257 template <typename LHSPropertiesT, typename RHSPropertiesT>
259 template <typename... LHSPropertiesTs, typename... RHSPropertiesTs>
260 struct merged_properties<properties_t<LHSPropertiesTs...>,
261  properties_t<RHSPropertiesTs...>> {
262  using type = properties<typename MergeProperties<
263  std::tuple<LHSPropertiesTs...>, std::tuple<RHSPropertiesTs...>>::type>;
264 };
265 template <typename LHSPropertiesT, typename RHSPropertiesT>
268 
269 template <typename Properties, typename PropertyKey, typename Cond = void>
271  template <typename ValT> static constexpr ValT get(ValT Default) {
272  return Default;
273  }
274 };
275 
276 template <typename Properties, typename PropertyKey>
278  Properties, PropertyKey,
279  std::enable_if_t<is_property_list_v<Properties> &&
280  Properties::template has_property<PropertyKey>()>> {
281  template <typename ValT> static constexpr ValT get(ValT) {
282  return Properties::template get_property<PropertyKey>().value;
283  }
284 };
285 
286 // helper: check_all_props_are_keys_of
287 template <typename SyclT> constexpr bool check_all_props_are_keys_of() {
288  return true;
289 }
290 
291 template <typename SyclT, typename FirstProp, typename... RestProps>
292 constexpr bool check_all_props_are_keys_of() {
294  SyclT>::value &&
295  check_all_props_are_keys_of<SyclT, RestProps...>();
296 }
297 
298 // all_props_are_keys_of
299 template <typename SyclT, typename PropertiesT>
300 struct all_props_are_keys_of : std::false_type {};
301 
302 template <typename SyclT>
305  : std::true_type {};
306 
307 template <typename SyclT, typename PropT>
310  : std::bool_constant<
311  ext::oneapi::experimental::is_property_key_of<PropT, SyclT>::value> {
312 };
313 
314 template <typename SyclT, typename... Props>
316  SyclT, ext::oneapi::experimental::detail::properties_t<Props...>>
317  : std::bool_constant<check_all_props_are_keys_of<SyclT, Props...>()> {};
318 
319 } // namespace detail
320 } // namespace ext::oneapi::experimental
321 
322 template <typename PropertiesT>
323 struct is_device_copyable<ext::oneapi::experimental::properties<PropertiesT>>
324  : is_device_copyable<PropertiesT> {};
325 } // namespace _V1
326 } // namespace sycl
std::enable_if_t< detail::IsRuntimeProperty< PropertyT >::value &&has_property< PropertyT >), PropertyT > get_property() const
Definition: properties.hpp:197
std::enable_if_t< detail::IsRuntimeProperty< PropertyT >::value &&!has_property< PropertyT >), void > get_property() const
Definition: properties.hpp:205
static constexpr auto get_property(typename std::enable_if_t< detail::IsCompileTimeProperty< PropertyT >::value > *=0)
Definition: properties.hpp:212
static constexpr std::enable_if_t< detail::IsProperty< PropertyT >::value, bool > has_property()
Definition: properties.hpp:189
constexpr properties(PropertyValueTs... props)
Definition: properties.hpp:172
static constexpr std::enable_if_t< HasProperty, typename FindCompileTimePropertyValueType< CTPropertyT, PropertiesT >::type > get_property()
Definition: properties.hpp:63
typename merged_properties< LHSPropertiesT, RHSPropertiesT >::type merged_properties_t
Definition: properties.hpp:267
Definition: access.hpp:18
static constexpr std::tuple< PropertyT, PropertiesTs... > Extract(const PropertyArgsT &PropertyValues)
Definition: properties.hpp:125
is_device_copyable is a user specializable class template to indicate that a type T is device copyabl...