workspace.hh
Go to the documentation of this file.
1#pragma once
2#include <cstddef>
3#include <cstdint>
4
5#include <batchlas/export.hh>
6
7/// @file
8/// @brief WorkspaceLease: a scoped borrow of scratch memory from a Queue's workspace arena.
9/// @see @ref design_workspace
10/// @ingroup api_workspace
11
12// No util/sycl-span.hh (include cycle through sycl-device-queue.hh): Span and Queue are forward
13// declared, and these MUST stay inside namespace batchlas or they declare different types.
14// evidence: docs/design/workspace.md#workspace-forward-declarations-in-workspacehh
15namespace batchlas {
16
17template <typename T>
18struct Span;
19
20struct Queue;
21
22/// @brief A borrow of scratch memory from a Queue's workspace arena, returned to the arena when
23/// the handle goes out of scope.
24///
25/// @code
26/// auto ws = ctx.workspace(foo_buffer_size<B>(ctx, A));
27/// foo<B>(ctx, A, ws.span());
28/// @endcode
29///
30/// Releasing a lease frees nothing (the memory belongs to the Queue), so the pointer stays valid
31/// for kernels still in flight; the bytes are handed to the *next* lease instead. On an in-order
32/// Queue that is safe by construction. On an out-of-order Queue, release() drains the queue first
33/// (see release()).
34///
35/// Leases nest, and the arena never moves leased memory. Release in reverse order of acquisition
36/// (scope-bound handles do this for free); an out-of-order release is safe but keeps its bytes
37/// reserved until every later lease is released, and debug builds assert on it.
38/// @warning Reassigning a live lease (`ws = ctx.workspace(bigger);`) acquires the new loan before
39/// the old one is returned, so a loop that reassigns every iteration ratchets the arena
40/// upward. Call `ws.release()` first.
41/// @note Tied to one Queue and not thread-safe, like Queue itself.
42/// @see @ref design_workspace
43/// @ingroup api_workspace
44// Class-level BATCHLAS_API, not per member: it must cover the PRIVATE release_(), which the inline
45// move-assignment calls. evidence: docs/design/symbol-visibility.md#symbol-visibility-workspacelease-is-exported-at-class-level
46class BATCHLAS_API WorkspaceLease {
47public:
48 /// @brief An empty lease that owns nothing.
49 WorkspaceLease() = default;
52
53 /// @brief Take over `other`'s loan; `other` becomes empty.
55 : queue_(other.queue_), ptr_(other.ptr_), size_(other.size_),
56 block_(other.block_), offset_(other.offset_), seq_(other.seq_) {
57 other.queue_ = nullptr;
58 other.ptr_ = nullptr;
59 other.size_ = 0;
60 other.seq_ = 0;
61 }
62
63 /// @brief Release this lease's loan, then take over `other`'s.
65 if (this != &other) {
66 // Out-of-order by construction (`other` was acquired first): legal, so no assert.
67 // evidence: docs/design/workspace.md#workspace-the-reassignment-ratchet
68 release_(/*diagnose_out_of_order=*/false);
69 queue_ = other.queue_;
70 ptr_ = other.ptr_;
71 size_ = other.size_;
72 block_ = other.block_;
73 offset_ = other.offset_;
74 seq_ = other.seq_;
75 other.queue_ = nullptr;
76 other.ptr_ = nullptr;
77 other.size_ = 0;
78 other.seq_ = 0;
79 }
80 return *this;
81 }
82
83 /// @brief Returns the loan to the arena (see release()).
85
86 /// @brief The borrowed bytes. Lvalue-only: the rvalue overload is deleted, because a span
87 /// taken from a temporary lease is stale on the next line.
88 // All three of `Span<std::byte> ws = ctx.workspace(n);`, `ctx.workspace(n).span()` and
89 // `.data()` aliased silently before. evidence: docs/design/workspace.md#workspace-lvalue-only-lease-accessors
91 Span<std::byte> span() const && = delete;
92 /// @brief Implicit conversion to the borrowed bytes; lvalue-only, as span().
93 operator Span<std::byte>() const &;
94 operator Span<std::byte>() const && = delete;
95
96 /// @brief Pointer to the borrowed bytes; lvalue-only, as span(). `nullptr` for an empty lease.
97 std::byte* data() const & { return ptr_; }
98 std::byte* data() const && = delete;
99 /// @brief Number of bytes borrowed.
100 std::size_t size() const { return size_; }
101
102 /// @brief Give the bytes back before the handle goes out of scope.
103 ///
104 /// Idempotent and never throws, so it is safe from a destructor. Free on an in-order Queue.
105 /// On an out-of-order Queue it blocks until the queue is idle when it actually hands bytes
106 /// back (when this is the innermost live lease); an out-of-order return only marks the loan.
107 /// @warning It waits only on the Queue the lease came from: it does not order against work
108 /// submitted to a Queue derived from it (`Queue(base, in_order)`). Pass your own span
109 /// for work on a sibling queue.
110 // evidence: docs/design/workspace.md#workspace-release-on-out-of-order-queues
111 void release() noexcept;
112
113private:
114 friend struct Queue;
115 // false suppresses the arena's debug assert for the one caller that must release out of order.
116 void release_(bool diagnose_out_of_order) noexcept;
117
118 WorkspaceLease(Queue* q, std::byte* p, std::size_t n, std::size_t block, std::size_t offset,
119 std::uint64_t seq)
120 : queue_(q), ptr_(p), size_(n), block_(block), offset_(offset), seq_(seq) {}
121
122 Queue* queue_ = nullptr;
123 std::byte* ptr_ = nullptr;
124 std::size_t size_ = 0;
125 std::size_t block_ = 0;
126 std::size_t offset_ = 0;
127 // Lets the arena tell an innermost release (rewind) from an out-of-order one (do not).
128 std::uint64_t seq_ = 0;
129};
130
131} // namespace batchlas
void release() noexcept
Give the bytes back before the handle goes out of scope.
Span< std::byte > span() const &
The borrowed bytes.
WorkspaceLease(const WorkspaceLease &)=delete
WorkspaceLease & operator=(const WorkspaceLease &)=delete
WorkspaceLease(WorkspaceLease &&other) noexcept
Take over other's loan; other becomes empty.
Definition workspace.hh:54
WorkspaceLease()=default
An empty lease that owns nothing.
WorkspaceLease & operator=(WorkspaceLease &&other) noexcept
Release this lease's loan, then take over other's.
Definition workspace.hh:64
~WorkspaceLease()
Returns the loan to the arena (see release()).
Definition workspace.hh:84
std::size_t size() const
Number of bytes borrowed.
Definition workspace.hh:100
std::byte * data() const &&=delete
std::byte * data() const &
Pointer to the borrowed bytes; lvalue-only, as span(). nullptr for an empty lease.
Definition workspace.hh:97
Where BatchLAS work runs: a device, a backend, an ordered SYCL queue and a workspace arena.
Non-owning view of size() contiguous elements of type T.
Definition sycl-span.hh:39