2 #ifndef UVCC_REQUEST_BASE__HPP 3 #define UVCC_REQUEST_BASE__HPP 5 #include "uvcc/debug.hpp" 6 #include "uvcc/utility.hpp" 14 #include <type_traits> 30 using uv_t = ::uv_req_t;
31 using on_destroy_t = std::function<
void(
void *_data) >;
40 constexpr static const std::size_t MAX_PROPERTY_SIZE = 24 +
sizeof(::
sockaddr_storage);
41 constexpr static const std::size_t MAX_PROPERTY_ALIGN = 8;
43 template<
class _Request_ >
class instance
47 template<
typename _T_,
typename = std::size_t >
struct substitute {
using type =
void; };
48 template<
typename _T_ >
struct substitute< _T_,
decltype(
sizeof(
typename _T_::uv_t)) > {
using type =
typename _T_::uv_t; };
49 using type =
typename substitute< _Request_ >::type;
53 template<
typename _T_,
typename = std::size_t >
struct substitute {
using type = std::function<
void() >; };
54 template<
typename _T_ >
struct substitute< _T_,
decltype(
sizeof(
typename _T_::on_request_t)) > {
using type =
typename _T_::on_request_t; };
55 using type =
typename substitute< _Request_ >::type;
59 mutable int uv_error = 0;
62 type_storage<
typename on_request_t::type > request_cb_storage;
63 aligned_storage< MAX_PROPERTY_SIZE, MAX_PROPERTY_ALIGN > property_storage;
65 alignas(::uv_any_req)
typename uv_t::type uv_req_struct;
70 std::memset(&uv_req_struct, 0,
sizeof(uv_req_struct));
71 property_storage.reset<
typename _Request_::properties >();
73 template<
typename... _Args_ > instance(_Args_&&... _args)
75 std::memset(&uv_req_struct, 0,
sizeof(uv_req_struct));
76 property_storage.reset<
typename _Request_::properties >(std::forward< _Args_ >(_args)...);
80 ~instance() =
default;
82 instance(
const instance&) =
delete;
83 instance& operator =(
const instance&) =
delete;
85 instance(instance&&) =
delete;
86 instance& operator =(instance&&) =
delete;
89 void destroy_instance()
91 auto &destroy_cb = destroy_cb_storage.value();
92 if (destroy_cb) destroy_cb(uv_req_struct.data);
98 static void* create() {
return &(
new instance)->uv_req_struct; }
99 template<
typename... _Args_ >
static void* create(_Args_&&... _args)
101 return &(
new instance(std::forward< _Args_ >(_args)...))->uv_req_struct;
104 constexpr static instance* from(
void *_uv_req)
noexcept 106 static_assert(std::is_standard_layout< instance >::value,
"not a standard layout type");
107 return reinterpret_cast< instance* >(
static_cast<
char* >(_uv_req) - offsetof(instance, uv_req_struct));
110 typename _Request_::properties& properties()
noexcept 111 {
return property_storage.get<
typename _Request_::properties >(); }
113 void ref() { refs.inc(); }
114 void unref() {
if (refs.dec() == 0) destroy_instance(); }
117 template<
class _Request_ >
friend typename _Request_::instance* debug::instance(_Request_&)
noexcept;
130 request()
noexcept : uv_req(
nullptr) {}
132 explicit request(uv_t *_uv_req)
134 if (_uv_req) instance< request >::from(_uv_req)->ref();
140 ~request() {
if (uv_req) instance< request >::from(uv_req)->unref(); }
142 request(
const request &_that) :
request(
static_cast< uv_t* >(_that.uv_req)) {}
147 if (_that.uv_req) instance< request >::from(_that.uv_req)->ref();
149 uv_req = _that.uv_req;
150 if (t) instance< request >::from(t)->unref();
155 request(
request &&_that)
noexcept : uv_req(_that.uv_req) { _that.uv_req =
nullptr; }
161 uv_req = _that.uv_req;
162 _that.uv_req =
nullptr;
163 if (t) instance< request >::from(t)->unref();
170 int uv_status(
int _value)
const noexcept 172 instance< request >::from(uv_req)->uv_error = _value;
178 void swap(
request &_that)
noexcept { std::swap(uv_req, _that.uv_req); }
179 std::uintptr_t id()
const noexcept {
return reinterpret_cast< std::uintptr_t >(instance< request >::from(uv_req)); }
182 long nrefs()
const noexcept {
return instance< request >::from(uv_req)->refs.get_value(); }
185 int uv_status()
const noexcept {
return instance< request >::from(uv_req)->uv_error; }
187 on_destroy_t& on_destroy()
const noexcept {
return instance< request >::from(uv_req)->destroy_cb_storage.value(); }
191 ::uv_req_type
type()
const noexcept {
return static_cast< uv_t* >(uv_req)->type; }
199 #define XX(X, x) case UV_##X: ret = #x; break; 202 default: ret =
"<unknown>";
break;
209 void*
const& data()
const noexcept {
return static_cast< uv_t* >(uv_req)->data; }
210 void* & data()
noexcept {
return static_cast< uv_t* >(uv_req)->data; }
214 int cancel()
noexcept {
return ::uv_cancel(
static_cast< uv_t* >(uv_req)); }
217 explicit operator
const uv_t*()
const noexcept {
return static_cast<
const uv_t* >(uv_req); }
218 explicit operator uv_t*()
noexcept {
return static_cast< uv_t* >(uv_req); }
220 explicit operator
bool()
const noexcept {
return (
uv_status() >= 0); }
231 template<>
inline void swap(
uv::
request &_this,
uv::
request &_that)
noexcept { _this.swap(_that); }
Namespace for all uvcc definitions.
The base class for the libuv requests.
A wrapper providing the feature of being a standard layout type for the given type _T_...
const char * type_name() const noexcept
A string containing the name of the request type.
long nrefs() const noexcept
The current number of existing references to the same object as this request variable refers to...
int uv_status() const noexcept
The status value returned by the last executed libuv API function on this request.
A reference counter with atomic increment/decrement.
::uv_req_type type() const noexcept
The tag indicating a libuv type of the request.