2 #ifndef UVCC_BUFFER__HPP 3 #define UVCC_BUFFER__HPP 5 #include "uvcc/debug.hpp" 6 #include "uvcc/utility.hpp" 11 #include <type_traits> 13 #include <initializer_list> 34 friend class udp_send;
40 using sink_cb_t = std::function<
void(
buffer&) >;
54 std::size_t buf_count;
58 static void* operator
new(std::size_t _size,
const std::initializer_list< std::size_t > &_len_values)
60 auto extra_buf_count = _len_values.size();
61 if (extra_buf_count > 0) --extra_buf_count;
62 std::size_t total_buf_len = 0;
63 for (
auto len : _len_values) total_buf_len += len;
64 return ::operator
new(_size + extra_buf_count*
sizeof(uv_t) + alignment_padding(extra_buf_count) + total_buf_len);
66 static void operator
delete(
void *_ptr,
const std::initializer_list< std::size_t >&) { ::operator
delete(_ptr); }
67 static void operator
delete(
void *_ptr) { ::operator
delete(_ptr); }
70 instance(
const std::initializer_list< std::size_t > &_len_values) : buf_count(_len_values.size())
75 uv_buf_struct.base =
nullptr;
76 uv_buf_struct.len = 0;
80 uv_t *buf = &uv_buf_struct;
81 std::size_t total_buf_len = 0;
82 for (
auto len : _len_values) total_buf_len += ((buf++)->len = len);
83 if (total_buf_len == 0)
86 for (
decltype(buf_count) i = 0; i < buf_count; ++i) { buf[i].base =
nullptr; buf[i].len = 0; }
90 uv_buf_struct.base =
reinterpret_cast<
char* >(buf) + alignment_padding(buf_count - 1);
92 for (
decltype(buf_count) i = 1; i < buf_count; ++i) buf[i].base = &buf[i-1].base[buf[i-1].len];
98 ~instance() =
default;
100 instance(
const instance&) =
delete;
101 instance& operator =(
const instance&) =
delete;
103 instance(instance&&) =
delete;
104 instance& operator =(instance&&) =
delete;
107 static std::size_t alignment_padding(
const std::size_t _extra_buf_count)
noexcept 109 const std::size_t base_size =
sizeof(instance) + _extra_buf_count*
sizeof(uv_t);
110 const std::size_t proper_size = (base_size +
alignof(std::max_align_t) - 1) & ~(
alignof(std::max_align_t) - 1);
111 return proper_size - base_size;
116 auto &sink_cb = sink_cb_storage.value();
120 buffer b(&uv_buf_struct, adopt_ref);
126 if (refs.dec() == 0)
delete this;
134 static uv_t* create(
const std::initializer_list< std::size_t > &_len_values)
135 {
return &(
new(_len_values) instance(_len_values))->uv_buf_struct; }
136 static uv_t* create() {
return create({}); }
138 constexpr static instance* from(uv_t *_uv_buf)
noexcept 140 static_assert(std::is_standard_layout< instance >::value,
"not a standard layout type");
141 return reinterpret_cast< instance* >(
reinterpret_cast<
char* >(_uv_buf) - offsetof(instance, uv_buf_struct));
146 static uv_t* from(
decltype(uv_t::base) _base)
noexcept 148 return reinterpret_cast< uv_t* >(
reinterpret_cast<
char* >(_base) - alignment_padding(0) -
sizeof(uv_t));
152 void ref() { refs.inc(); }
153 void unref()
noexcept {
if (refs.dec() == 0) destroy(); }
156 friend typename buffer::instance* debug::instance<>(buffer&)
noexcept;
163 explicit buffer(uv_t *_uv_buf)
165 if (_uv_buf) instance::from(_uv_buf)->ref();
169 explicit buffer(uv_t *_uv_buf,
const adopt_ref_t) : uv_buf(_uv_buf) {}
172 ~buffer() {
if (uv_buf) instance::from(uv_buf)->unref(); }
201 buffer(
const buffer &_that) : buffer(_that.uv_buf) {}
206 if (_that.uv_buf) instance::from(_that.uv_buf)->ref();
208 uv_buf = _that.uv_buf;
209 if (t) instance::from(t)->unref();
214 buffer(
buffer &&_that)
noexcept : uv_buf(_that.uv_buf) { _that.uv_buf =
nullptr; }
220 uv_buf = _that.uv_buf;
221 _that.uv_buf =
nullptr;
222 if (t) instance::from(t)->unref();
228 void swap(
buffer &_that)
noexcept { std::swap(uv_buf, _that.uv_buf); }
230 long nrefs()
const noexcept {
return instance::from(uv_buf)->refs.get_value(); }
232 sink_cb_t& sink_cb()
const noexcept {
return instance::from(uv_buf)->sink_cb_storage.value(); }
235 std::size_t
count()
const noexcept {
return instance::from(uv_buf)->buf_count; }
266 using on_buffer_alloc_t = std::function<
buffer(
handle _handle, std::size_t _suggested_size) >;
276 template<>
inline void swap(
uv::
buffer &_this,
uv::
buffer &_that)
noexcept { _this.swap(_that); }
Namespace for all uvcc definitions.
operator bool() const noexcept
Equivalent to (base() != nullptr).
A wrapper providing the feature of being a standard layout type for the given type _T_...
buffer(const std::initializer_list< std::size_t > &_len_values)
Create an array of initialized uv_buf_t buffer describing structures.
std::size_t count() const noexcept
The number of the uv_buf_t structures in the array.
decltype(uv_t::len) & len(const std::size_t _i=0) const noexcept
The .len field of the _i-th buffer structure.
uv_t & operator[](const std::size_t _i) const noexcept
Access to the _i-th uv_buf_t buffer structure in the array.
The base class for the libuv handles.
long nrefs() const noexcept
The current number of existing references to the same buffer as this variable refers to...
A reference counter with atomic increment/decrement.
decltype(uv_t::base) & base(const std::size_t _i=0) const noexcept
The .base field of the _i-th buffer structure.
buffer()
Create a single uv_buf_t null-initialized buffer structure.