userver: userver/engine/io/common.hpp Source File
Loading...
Searching...
No Matches
common.hpp
Go to the documentation of this file.
1#pragma once
2
3/// @file userver/engine/io/common.hpp
4/// @brief Common definitions and base classes for stream like objects
5
6#include <cstddef>
7#include <memory>
8#include <optional>
9#include <span>
10
11#include <userver/compiler/impl/lifetime.hpp>
12#include <userver/engine/awaitable.hpp>
13#include <userver/engine/deadline.hpp>
14#include <userver/utils/assert.hpp>
15#include <userver/utils/impl/internal_tag.hpp>
16
17USERVER_NAMESPACE_BEGIN
18
19namespace engine::impl {
20class AwaitableBase;
21}
22
23namespace engine::io {
24
25/// File descriptor of an invalid pipe end.
26inline constexpr int kInvalidFd = -1;
27
28/// @ingroup userver_base_classes
29///
30/// Base class for readable stream waiting
32public:
33 virtual ~ReadAwaiter();
34
35 /// Suspends current task until the stream has data available.
36 [[nodiscard]] virtual bool WaitReadable(Deadline) = 0;
37
38 /// Satisfies @ref engine::Awaitable, for use with @ref engine::WaitAnyContext and friends.
39 AwaitableToken GetAwaitableToken() USERVER_IMPL_LIFETIME_BOUND {
40 return AwaitableToken{utils::impl::InternalTag{}, ca_};
41 }
42
43protected:
44 void SetReadableAwaitableToken(AwaitableToken token) {
45 ca_ = token.IsEmpty() ? nullptr : &token.GetAwaitable(utils::impl::InternalTag{});
46 }
47
48private:
49 impl::AwaitableBase* ca_{nullptr};
50};
51
52/// @ingroup userver_base_classes
53///
54/// Interface for readable streams
55class ReadableBase : public ReadAwaiter {
56public:
57 ~ReadableBase() override;
58
59 /// Whether the stream is valid.
60 virtual bool IsValid() const = 0;
61
62 /// Receives up to len (including zero) bytes from the stream.
63 /// @returns filled-in optional on data presence (e.g. 0, 1, 2... bytes)
64 /// empty optional otherwise
65 [[nodiscard]] virtual std::optional<size_t> ReadNoblock(void* buf, size_t len) {
66 (void)buf;
67 (void)len;
68 UINVARIANT(false, "not implemented yet");
69 return {};
70 }
71
72 /// Receives at least one byte from the stream.
73 [[nodiscard]] virtual size_t ReadSome(void* buf, size_t len, Deadline deadline) = 0;
74
75 /// Receives exactly len bytes from the stream.
76 /// @note Can return less than len if stream is closed by peer.
77 [[nodiscard]] virtual size_t ReadAll(void* buf, size_t len, Deadline deadline) = 0;
78};
79
80/// @ingroup userver_base_classes
81///
82/// Base class for writable stream waiting
84public:
85 virtual ~WriteAwaiter();
86
87 /// Suspends current task until the data is available.
88 [[nodiscard]] virtual bool WaitWriteable(Deadline deadline) = 0;
89
90 /// Satisfies @ref engine::Awaitable, for use with @ref engine::WaitAnyContext and friends.
91 AwaitableToken GetAwaitableToken() USERVER_IMPL_LIFETIME_BOUND {
92 return AwaitableToken{utils::impl::InternalTag{}, ca_};
93 }
94
95protected:
96 void SetWritableAwaitableToken(AwaitableToken token) {
97 ca_ = token.IsEmpty() ? nullptr : &token.GetAwaitable(utils::impl::InternalTag{});
98 }
99
100private:
101 impl::AwaitableBase* ca_{nullptr};
102};
103
104/// IoData for vector send
105struct IoData final {
106 const void* data;
107 size_t len;
108};
109
110/// @ingroup userver_base_classes
111///
112/// Interface for writable streams
114public:
115 ~WritableBase() override;
116
117 /// @brief Sends exactly len bytes of buf.
118 /// @note Can return less than len if stream is closed by peer.
119 [[nodiscard]] virtual size_t WriteAll(const void* buf, size_t len, Deadline deadline) = 0;
120
121 /// @brief Sends IoData array using vector I/O (e.g. writev).
122 /// @note Can return less than total bytes if stream is closed by peer.
123 [[nodiscard]] virtual size_t WriteAll(std::span<const IoData> list, Deadline deadline) {
124 size_t result{0};
125 for (const auto& io_data : list) {
126 result += WriteAll(io_data.data, io_data.len, deadline);
127 }
128 return result;
129 }
130
131 /// @brief Sends IoData initializer list using vector I/O (e.g. writev).
132 /// @note Can return less than total bytes if stream is closed by peer.
133 [[nodiscard]] virtual size_t WriteAll(std::initializer_list<IoData> list, Deadline deadline) {
134 return WriteAll(std::span<const IoData>{list.begin(), list.size()}, deadline);
135 }
136};
137
138/// @ingroup userver_base_classes
139///
140/// Interface for readable and writable streams
141// NOLINTNEXTLINE(fuchsia-multiple-inheritance)
142class RwBase : public ReadableBase, public WritableBase {
143public:
144 ~RwBase() override;
145
146 ReadableBase& GetReadableBase() { return *this; }
147
148 WritableBase& GetWritableBase() { return *this; }
149};
150
151using ReadableBasePtr = std::shared_ptr<ReadableBase>;
152
153} // namespace engine::io
154
155USERVER_NAMESPACE_END