2 #ifndef UVCC_HANDLE_IO__HPP 3 #define UVCC_HANDLE_IO__HPP 5 #include "uvcc/utility.hpp" 6 #include "uvcc/handle-base.hpp" 7 #include "uvcc/buffer.hpp" 8 #include "uvcc/loop.hpp" 28 friend class handle::instance< io >;
36 using on_read_t = std::function<
void(
io _handle, ssize_t _nread,
buffer _buffer, int64_t _offset,
void *_info) >;
65 enum class rdcmd { UNKNOWN, STOP, PAUSE, START, RESUME };
67 struct properties :
handle::properties
70 rdcmd rdcmd_state = rdcmd::UNKNOWN;
71 std::size_t rdsize = 0;
73 on_buffer_alloc_t alloc_cb;
77 struct uv_interface :
virtual handle::uv_interface
79 virtual std::size_t write_queue_size(
void*)
const noexcept = 0;
80 virtual int read_start(
void*, int64_t)
const noexcept = 0;
81 virtual int read_stop(
void*)
const noexcept = 0;
88 using instance =
handle::instance<
io >;
92 io()
noexcept =
default;
94 explicit io(uv_t *_uv_handle) :
handle(
static_cast<
handle::uv_t* >(_uv_handle)) {}
100 io(
const io&) =
default;
101 io& operator =(
const io&) =
default;
103 io(
io&&)
noexcept =
default;
104 io& operator =(
io&&)
noexcept =
default;
108 static void io_alloc_cb(uv_t *_uv_handle, std::size_t _suggested_size, ::uv_buf_t *_uv_buf)
110 auto &properties = instance::from(_uv_handle)->properties();
112 auto &alloc_cb = properties.alloc_cb;
113 buffer &&b = alloc_cb(io(_uv_handle), properties.rdsize ? properties.rdsize : _suggested_size);
115 buffer::instance::from(b.uv_buf)->ref();
119 static void io_read_cb(uv_t *_uv_handle, ssize_t _nread,
const ::uv_buf_t *_uv_buf,
void *_info)
121 auto instance_ptr = instance::from(_uv_handle);
122 auto &properties = instance_ptr->properties();
124 instance_ptr->uv_error = _nread;
126 auto &read_cb = properties.read_cb;
128 read_cb(io(_uv_handle), _nread, buffer(buffer::instance::uv_buf::from(_uv_buf->base), adopt_ref), properties.rdoffset, _info);
133 read_cb(io(_uv_handle), _nread, buffer(), properties.rdoffset, _info);
135 if (_nread > 0) properties.rdoffset += _nread;
149 std::size_t
write_queue_size()
const noexcept {
return instance::from(uv_handle)->uv_interface()->write_queue_size(uv_handle); }
152 on_buffer_alloc_t&
on_alloc()
const noexcept {
return instance::from(uv_handle)->properties().alloc_cb; }
155 on_read_t&
on_read()
const noexcept {
return instance::from(uv_handle)->properties().read_cb; }
191 int read_start(std::size_t _size = 0, int64_t _offset = -1)
const 193 auto instance_ptr = instance::from(uv_handle);
194 auto &properties = instance_ptr->properties();
196 std::lock_guard<
decltype(properties.rdstate_switch) > lk(properties.rdstate_switch);
198 if (!properties.alloc_cb
or !properties.read_cb)
return uv_status(UV_EINVAL);
200 auto rdcmd_state0 = properties.rdcmd_state;
202 properties.rdcmd_state = rdcmd::START;
205 switch (rdcmd_state0)
213 uv_status(instance_ptr->uv_interface()->read_stop(uv_handle));
214 instance_ptr->unref();
218 properties.rdsize = _size;
221 auto uv_ret = instance_ptr->uv_interface()->read_start(uv_handle, _offset);
225 properties.rdcmd_state = rdcmd::UNKNOWN;
226 instance_ptr->unref();
241 int read_start(
const on_buffer_alloc_t &_alloc_cb,
const on_read_t &_read_cb, std::size_t _size = 0, int64_t _offset = -1)
const 243 auto &properties = instance::from(uv_handle)->properties();
245 properties.alloc_cb = _alloc_cb;
246 properties.read_cb = _read_cb;
256 auto instance_ptr = instance::from(uv_handle);
257 auto &properties = instance_ptr->properties();
259 std::lock_guard<
decltype(properties.rdstate_switch) > lk(properties.rdstate_switch);
261 auto rdcmd_state0 = properties.rdcmd_state;
262 properties.rdcmd_state = rdcmd::STOP;
264 auto uv_ret = uv_status(instance_ptr->uv_interface()->read_stop(uv_handle));
266 switch (rdcmd_state0)
274 instance_ptr->unref();
291 if (!_trigger_condition)
return 1;
293 auto instance_ptr = instance::from(uv_handle);
294 auto &properties = instance_ptr->properties();
296 std::lock_guard<
decltype(properties.rdstate_switch) > lk(properties.rdstate_switch);
299 switch (properties.rdcmd_state)
307 properties.rdcmd_state = rdcmd::PAUSE;
308 ret = uv_status(instance_ptr->uv_interface()->read_stop(uv_handle));
309 instance_ptr->unref();
348 if (!_trigger_condition)
return 1;
350 auto instance_ptr = instance::from(uv_handle);
351 auto &properties = instance_ptr->properties();
353 std::lock_guard<
decltype(properties.rdstate_switch) > lk(properties.rdstate_switch);
356 switch (properties.rdcmd_state)
362 properties.rdcmd_state = rdcmd::RESUME;
366 ret = instance_ptr->uv_interface()->read_start(uv_handle, properties.rdoffset);
370 properties.rdcmd_state = rdcmd::UNKNOWN;
371 instance_ptr->unref();
391 explicit operator
const uv_t*()
const noexcept {
return static_cast<
const uv_t* >(uv_handle); }
392 explicit operator uv_t*()
noexcept {
return static_cast< uv_t* >(uv_handle); }
399 #include "uvcc/handle-stream.hpp" 400 #include "uvcc/handle-fs.hpp" 401 #include "uvcc/handle-udp.hpp" 412 switch (::uv_guess_handle(_fd))
415 case UV_UNKNOWN_HANDLE: ret.uv_status(UV_EBADF);
417 case UV_NAMED_PIPE: ret = pipe(_loop, _fd,
false,
false);
419 case UV_TCP: ret = tcp(_loop, _fd,
false);
421 case UV_TTY: ret = tty(_loop, _fd,
true,
false);
423 case UV_UDP: ret = udp(_loop,
static_cast< ::uv_os_sock_t >(_fd));
425 case UV_FILE: ret = file(_loop, _fd);
Namespace for all uvcc definitions.
operator bool() const noexcept
Equivalent to (base() != nullptr).
A simple spinlock mutex built around std::atomic_flag.
int read_resume(bool _trigger_condition)
Resume reading data from the I/O endpoint after having been paused.
int read_start(const on_buffer_alloc_t &_alloc_cb, const on_read_t &_read_cb, std::size_t _size=0, int64_t _offset=-1) const
Start reading incoming data from the I/O endpoint with provided input buffer allocation callback (_al...
int read_pause(bool _trigger_condition) const
Pause reading data from the I/O endpoint.
std::size_t write_queue_size() const noexcept
The amount of queued bytes waiting to be written/sent to the I/O endpoint.
int read_stop() const
Stop reading data from the I/O endpoint.
The base class for the libuv handles.
The I/O event loop class.
The base class for handles representing I/O endpoints: a file, TCP/UDP socket, pipe, TTY.
on_buffer_alloc_t & on_alloc() const noexcept
Set the input buffer allocation callback.
static io guess_handle(uv::loop &, ::uv_file)
Create an io handle object which actual type is derived from an existing file descriptor.
int read_start(std::size_t _size=0, int64_t _offset=-1) const
Start reading incoming data from the I/O endpoint.
on_read_t & on_read() const noexcept
Set the read callback function.