uvco 0.1
Loading...
Searching...
No Matches
uvco::StreamBase Class Reference

A plain stream, permitting reading, writing, and closing. More...

#include <stream.h>

Inheritance diagram for uvco::StreamBase:

Classes

struct  InStreamAwaiter_
struct  OutStreamAwaiter_
struct  ShutdownAwaiter_

Public Member Functions

template<typename Stream>
 StreamBase (std::unique_ptr< Stream > stream)
 StreamBase (const StreamBase &)=delete
 StreamBase (StreamBase &&)=default
StreamBaseoperator= (const StreamBase &)=delete
StreamBaseoperator= (StreamBase &&)=default
virtual ~StreamBase ()
Promise< std::optional< std::string > > read (size_t maxSize=defaultMaxReadSize)
Promise< size_t > read (std::span< char > buffer)
Promise< size_t > write (std::string buf)
Promise< size_t > writeBorrowed (std::span< const char > buf)
Promise< void > shutdown ()
void close ()
const uv_stream_t * underlying () const
 Return the underlying UV stream object.
uv_os_fd_t fd () const

Static Public Attributes

static constexpr size_t defaultMaxReadSize = 4080

Protected Member Functions

uv_stream_t & stream ()
void destroyStream ()

Private Attributes

std::unique_ptr< uv_stream_t, UvHandleDeleterstream_
std::coroutine_handle reader_
std::coroutine_handle writer_

Detailed Description

A plain stream, permitting reading, writing, and closing.

Constructor & Destructor Documentation

◆ StreamBase() [1/3]

template<typename Stream>
uvco::StreamBase::StreamBase ( std::unique_ptr< Stream > stream)
inlineexplicit
38 : stream_{(uv_stream_t *)stream.release()} {}
uv_stream_t & stream()
Definition stream.h:105
std::unique_ptr< uv_stream_t, UvHandleDeleter > stream_
Definition stream.h:115

◆ StreamBase() [2/3]

uvco::StreamBase::StreamBase ( const StreamBase & )
delete

◆ StreamBase() [3/3]

uvco::StreamBase::StreamBase ( StreamBase && )
default

◆ ~StreamBase()

uvco::StreamBase::~StreamBase ( )
virtual

Closes the stream if not already closed. It's always best to explicitly call co_await stream.close(), but as a backup, the destructor will close the stream if still open. To do so, it will schedule a callback on the libuv loop.

84{ close(); }
void close()
Definition stream.cc:155

Member Function Documentation

◆ close()

void uvco::StreamBase::close ( )

Informs pending readers and writers of the close and causes them to return an empty optional.

155 {
156 if (stream_ != nullptr) {
157 closeHandle(stream_.release());
158 }
159 if (reader_ != nullptr) {
160 std::coroutine_handle<> reader = reader_;
161 reader_ = nullptr;
162 reader.resume();
163 }
164 if (writer_ != nullptr) {
165 std::coroutine_handle<> writer = writer_;
166 writer_ = nullptr;
167 writer.resume();
168 }
169}
std::coroutine_handle reader_
Definition stream.h:118
std::coroutine_handle writer_
Definition stream.h:119
void closeHandle(Handle *handle, void(*closer)(CloserArg *, void(*)(uv_handle_t *)))
Definition close.h:37

◆ destroyStream()

void uvco::StreamBase::destroyStream ( )
inlineprotected
109 {
110 BOOST_ASSERT(stream_);
111 stream_.reset();
112 }

◆ fd()

uv_os_fd_t uvco::StreamBase::fd ( ) const
nodiscard
343 {
344 uv_os_fd_t fd{};
345 const uv_status status = uv_fileno((uv_handle_t *)stream_.get(), &fd);
346 if (status != 0) {
347 throw UvcoException(status, "StreamBase::fd(): uv_fileno() failed: " +
348 std::string{uv_strerror(status)});
349 }
350 return fd;
351}
uv_os_fd_t fd() const
Definition stream.cc:343
int uv_status
Result of a libuv operation, an errno error code.
Definition internal_utils.h:22

◆ operator=() [1/2]

StreamBase & uvco::StreamBase::operator= ( const StreamBase & )
delete

◆ operator=() [2/2]

StreamBase & uvco::StreamBase::operator= ( StreamBase && )
default

◆ read() [1/2]

Promise< std::optional< std::string > > uvco::StreamBase::read ( size_t maxSize = defaultMaxReadSize)
nodiscard

Read available data (up to maxSize bytes) from stream. Returns std::nullopt on EOF or closed handle (close()).

Throws UvcoException on error.

NOTE: Consider using read(std::span<char>) for better performance.

NOTE: only one reader is allowed to be active at a time. If a read is started while another is still active, uvco will abort the process (in Debug mode), or ignore the first read (in Release mode).

96 {
97 // This is a promise root function, i.e. origin of a promise.
98 std::string buf(maxSize, '\0');
99 InStreamAwaiter_ awaiter{*this, buf};
100 const size_t nRead = co_await awaiter;
101 if (nRead == 0) {
102 // EOF.
103 co_return std::nullopt;
104 }
105 buf.resize(nRead);
106 co_return buf;
107}
Definition stream.cc:40

◆ read() [2/2]

Promise< size_t > uvco::StreamBase::read ( std::span< char > buffer)

Read available data (up to buffer.size() bytes) from stream. Returns the number of bytes read, or 0 on EOF or closed handle (close()).

Only one read() coroutine may be active at a time. The stream must outlive the coroutine, i.e. live until co_await stream.read(...) returns a result.

Throws UvcoException on error.

109 {
110 InStreamAwaiter_ awaiter{*this, buffer};
111 co_return (co_await awaiter);
112}

◆ shutdown()

Promise< void > uvco::StreamBase::shutdown ( )
nodiscard

Shut down stream for writing. This is a half-close; the other side can still write. The result of shutdown() must be co_awaited.

144 {
145 uv_shutdown_t shutdownReq;
146 ShutdownAwaiter_ awaiter;
147
148 shutdownReq.data = &awaiter;
149 uv_shutdown(&shutdownReq, &stream(),
151 co_await awaiter;
152 co_return;
153}
Definition stream.cc:28
static void onShutdown(uv_shutdown_t *req, uv_status status)
Definition stream.cc:333

◆ stream()

uv_stream_t & uvco::StreamBase::stream ( )
inlineprotected
105 {
106 BOOST_ASSERT(stream_);
107 return *stream_;
108 }

◆ underlying()

const uv_stream_t * uvco::StreamBase::underlying ( ) const
inlinenodiscard

Return the underlying UV stream object.

100{ return stream_.get(); }

◆ write()

Promise< size_t > uvco::StreamBase::write ( std::string buf)
nodiscard

Write a buffer to the stream. A copy of buf is taken because it is undetermined when the actual write will occur. Await the result if the status is important; the write will be executed even without awaiting (as long as the process keeps running).

NOTE: only one writer is allowed to be active at a time. If two writes are started simultaneously, the process will be aborted in Debug mode, or the first write() coroutine will not return in Release mode.

114 {
115 co_return (co_await writeBorrowed(std::span{buf}));
116}
Promise< size_t > writeBorrowed(std::span< const char > buf)
Definition stream.cc:118

◆ writeBorrowed()

Promise< size_t > uvco::StreamBase::writeBorrowed ( std::span< const char > buf)
nodiscard

The same as write(std::string), but takes a borrowed buffer. buf MUST absolutely stay valid until the promise resolves. This means: co_await this method and call it with a stored buffer (not a function return value, for example).

118 {
119 OutStreamAwaiter_ awaiter{*this, buffer};
120 std::array<uv_buf_t, 1> bufs{};
121 bufs[0] = uv_buf_init(const_cast<char *>(buffer.data()), buffer.size());
122
123 uv_status status = uv_try_write(&stream(), bufs.data(), bufs.size());
124 if (status > 0) {
125 // Already done, nothing had to be queued.
126 co_return static_cast<size_t>(status);
127 }
128
129 status = uv_write(&awaiter.write_, &stream(), bufs.data(), bufs.size(),
131 if (status < 0) {
132 throw UvcoException{
133 status, "StreamBase::writeBorrowed() encountered error in uv_write"};
134 }
135 status = co_await awaiter;
136 if (status < 0) {
137 throw UvcoException{
138 status,
139 "StreamBase::writeBorrowed() encountered error while awaiting write"};
140 }
141 co_return static_cast<size_t>(status);
142}
static void onOutStreamWrite(uv_write_t *write, uv_status status)
Definition stream.cc:306

Member Data Documentation

◆ defaultMaxReadSize

size_t uvco::StreamBase::defaultMaxReadSize = 4080
staticconstexpr

◆ reader_

std::coroutine_handle uvco::StreamBase::reader_
private

◆ stream_

std::unique_ptr<uv_stream_t, UvHandleDeleter> uvco::StreamBase::stream_
private

◆ writer_

std::coroutine_handle uvco::StreamBase::writer_
private

The documentation for this class was generated from the following files: