@@ -54,37 +54,38 @@ class LockedBufferSpan {
5454 using iterator = T*;
5555 using const_iterator = const T*;
5656
57- // `const std::byte*` if `T` is `const`, otherwise `std::byte`.
58- using MaybeConstByte =
59- std::conditional_t <std::is_const_v<T>, const std::byte, std::byte>;
60-
61- LockedBufferSpan (MaybeConstByte* data,
62- std::function<void (MaybeConstByte*)> unlock, size_t bytes)
63- : data_(data, std::move(unlock)), bytes_(bytes) {}
64-
65- LockedBufferSpan (
66- std::unique_ptr<MaybeConstByte, std::function<void (MaybeConstByte*)>>
67- data,
68- size_t bytes)
69- : data_(std::move(data)), bytes_(bytes) {}
57+ template <class Unlock >
58+ LockedBufferSpan (T* data, Unlock&& unlock, size_t count)
59+ : data_(data, std::forward<Unlock>(unlock)), bytes_(count * sizeof (T)) {}
60+
61+ template <class Y , class Deleter >
62+ LockedBufferSpan (std::unique_ptr<Y, Deleter> data, size_t count)
63+ : data_(data.release(), data.get_deleter()), bytes_(count * sizeof (T)) {}
7064
7165 static LockedBufferSpan Empty () {
72- return LockedBufferSpan (nullptr , [](MaybeConstByte *) {}, 0 );
66+ return LockedBufferSpan (nullptr , [](T *) {}, 0 );
7367 }
7468
7569 // Casts the span to a specific type.
76- //
77- // Warning: This transfers the lock management to the returned
78- // `LockedBufferSpan`.
7970 template <class U >
80- [[nodiscard]] LockedBufferSpan<U> As () && {
71+ [[nodiscard]] LockedBufferSpan<U> As () const {
8172 static_assert (
8273 std::is_const_v<U> || !std::is_const_v<T>,
8374 " Cannot cast from a constant buffer span to a non constant one." );
84- return LockedBufferSpan<U>(std::move (data_), bytes_);
75+ return LockedBufferSpan<U>(data_, reinterpret_cast <U*>(data_.get ()),
76+ bytes_ / sizeof (U));
77+ }
78+
79+ [[nodiscard]] LockedBufferSpan SubSpan (size_t offset,
80+ size_t count = SIZE_MAX ) const {
81+ if (offset >= size ()) {
82+ return Empty ();
83+ }
84+ const size_t sub_count = std::min (count, size () - offset);
85+ return LockedBufferSpan (data_, data_.get () + offset, sub_count);
8586 }
8687
87- T* data () const & { return reinterpret_cast <T*>( data_.get () ); }
88+ T* data () const & { return data_.get (); }
8889 size_t size () const { return bytes_ / sizeof (T); }
8990 T* begin () & { return data (); }
9091 T* end () & { return data () + size (); }
@@ -102,8 +103,15 @@ class LockedBufferSpan {
102103 const T* cend () const && = delete;
103104
104105 private:
105- std::unique_ptr<MaybeConstByte, std::function<void (MaybeConstByte*)>> data_;
106- size_t bytes_;
106+ template <class >
107+ friend class LockedBufferSpan ;
108+
109+ template <class U >
110+ LockedBufferSpan (const std::shared_ptr<U>& data, T* ptr, size_t count)
111+ : data_(data, ptr), bytes_(count * sizeof (T)) {}
112+
113+ std::shared_ptr<T> data_;
114+ size_t bytes_ = 0 ;
107115};
108116
109117// The main interface for buffers.
0 commit comments