Skip to content

Commit 528d43a

Browse files
[SYCL][NFCI] Unify queue submit paths (#15776)
The submit method on queue has caused multiple divergences throughout its lifetime, when additional information was required for new functionality. However, that design means an exponential growth in functions every time a new optional argument is needed. To battle this, this patch adds a new pimpl class with the optional submission info, which will only be initialized if needed. This boils the submit function paths down to one with event and one without. --------- Signed-off-by: Larsen, Steffen <[email protected]>
1 parent b03552a commit 528d43a

File tree

8 files changed

+389
-146
lines changed

8 files changed

+389
-146
lines changed

sycl/include/sycl/detail/optional.hpp

Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
//==-------- optional.hpp - limited variant of std::optional -------- C++ --==//
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+
11+
#include <optional>
12+
#include <type_traits>
13+
14+
namespace sycl {
15+
inline namespace _V1 {
16+
namespace detail {
17+
18+
// ABI-stable implementation of optional to avoid reliance on potentially
19+
// differing implementations of std::optional when crossing the library
20+
// boundary.
21+
template <typename T> class optional {
22+
public:
23+
constexpr optional() noexcept {}
24+
constexpr optional(std::nullopt_t) noexcept : optional() {}
25+
26+
template <typename U>
27+
constexpr optional(const optional<U> &Other)
28+
: ContainsValue{Other.ContainsValue} {
29+
new (Storage) T(Other.Value);
30+
}
31+
template <typename U>
32+
constexpr optional(optional<U> &&Other)
33+
: ContainsValue{std::move(Other.ContainsValue)} {
34+
new (Storage) T(std::move(Other.Value));
35+
}
36+
37+
constexpr optional(T &&Value) : ContainsValue{true} {
38+
new (Storage) T(std::move(Value));
39+
}
40+
41+
constexpr optional(const T &Value) : ContainsValue{true} {
42+
new (Storage) T(Value);
43+
}
44+
45+
template <typename U>
46+
constexpr optional(const std::optional<U> &Other) : ContainsValue{Other} {
47+
if (Other)
48+
new (Storage) T(*Other);
49+
}
50+
51+
~optional() {
52+
if (has_value())
53+
reinterpret_cast<T *>(Storage)->~T();
54+
}
55+
56+
optional &operator=(std::nullopt_t) noexcept {
57+
if (has_value())
58+
reinterpret_cast<T *>(Storage)->~T();
59+
ContainsValue = false;
60+
return *this;
61+
}
62+
63+
template <typename U> optional &operator=(const optional<U> &Other) {
64+
if (has_value())
65+
reinterpret_cast<T *>(Storage)->~T();
66+
ContainsValue = Other;
67+
new (Storage) T(Other.Value);
68+
return *this;
69+
}
70+
template <typename U> optional &operator=(optional<U> &&Other) noexcept {
71+
if (has_value())
72+
reinterpret_cast<T *>(Storage)->~T();
73+
ContainsValue = Other;
74+
new (Storage) T(std::move(Other.Value));
75+
return *this;
76+
}
77+
78+
optional &operator=(T &&Value) {
79+
if (has_value())
80+
reinterpret_cast<T *>(Storage)->~T();
81+
ContainsValue = true;
82+
new (Storage) T(std::move(Value));
83+
return *this;
84+
}
85+
86+
optional &operator=(const T &Value) {
87+
if (has_value())
88+
reinterpret_cast<T *>(Storage)->~T();
89+
ContainsValue = true;
90+
new (Storage) T(Value);
91+
return *this;
92+
}
93+
94+
template <typename U> optional &operator=(const std::optional<U> &Other) {
95+
if (has_value())
96+
reinterpret_cast<T *>(Storage)->~T();
97+
ContainsValue = Other;
98+
if (Other)
99+
new (Storage) T(*Other);
100+
return *this;
101+
}
102+
103+
constexpr bool has_value() const noexcept { return ContainsValue; }
104+
constexpr explicit operator bool() const noexcept { return has_value(); }
105+
106+
constexpr T &value() & {
107+
if (!has_value())
108+
throw std::bad_optional_access{};
109+
return *reinterpret_cast<T *>(Storage);
110+
}
111+
constexpr const T &value() const & {
112+
if (!has_value())
113+
throw std::bad_optional_access{};
114+
return *reinterpret_cast<const T *>(Storage);
115+
}
116+
constexpr T &&value() && {
117+
if (!has_value())
118+
throw std::bad_optional_access{};
119+
return std::move(*reinterpret_cast<T *>(Storage));
120+
}
121+
constexpr const T &&value() const && {
122+
if (!has_value())
123+
throw std::bad_optional_access{};
124+
return std::move(*reinterpret_cast<const T *>(Storage));
125+
}
126+
127+
template <class U> constexpr T value_or(U &&DefaultVal) {
128+
return has_value() ? value() : static_cast<T>(std::forward<U>(DefaultVal));
129+
}
130+
template <class U> constexpr T value_or(U &&DefaultVal) const {
131+
return has_value() ? std::move(value())
132+
: static_cast<T>(std::forward<U>(DefaultVal));
133+
}
134+
135+
constexpr T &operator*() & { return value(); }
136+
constexpr const T &operator*() const & { return value(); }
137+
constexpr T &&operator*() && { return value(); }
138+
constexpr const T &&operator*() const && { return value(); }
139+
140+
private:
141+
alignas(alignof(T)) char Storage[sizeof(T)] = {0};
142+
bool ContainsValue = false;
143+
};
144+
145+
} // namespace detail
146+
} // namespace _V1
147+
} // namespace sycl

0 commit comments

Comments
 (0)