userver: userver/engine/io/fd_poller.hpp Source File
⚠️ This is the documentation for an old userver version. Click here to switch to the latest version.
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages Concepts
fd_poller.hpp
Go to the documentation of this file.
1#pragma once
2
3/// @file userver/engine/io/fd_poller.hpp
4/// @brief Low-level file descriptor r/w poller
5
6#include <memory>
7#include <optional>
8
9#include <userver/engine/deadline.hpp>
10#include <userver/utils/fast_pimpl.hpp>
11
12USERVER_NAMESPACE_BEGIN
13
14namespace engine::io {
15
16namespace impl {
17class Direction;
18}
19
20/// @brief Low-level poller that can wait for read, write, and read/write
21/// operations on a file descriptor. It does not provide read/write operations.
22/// @note FdPoller is not thread safe and its methods must not be called from
23/// multiple threads simultaneously.
24class FdPoller final {
25 public:
26 /// @brief Operation kind to wait for
27 enum class Kind {
28 kRead = 1, /// < wait for read availability
29 kWrite = 2, /// < wait for write availability
30 kReadWrite = 3, /// < wait for either read or write availability
31 };
32
33 FdPoller();
34 FdPoller(const FdPoller&) = delete;
35 FdPoller(FdPoller&&) = delete;
36 FdPoller& operator=(const FdPoller&) = delete;
37 FdPoller& operator=(FdPoller&&) = delete;
38 ~FdPoller();
39
40 /// The same as `IsValid()`.
41 explicit operator bool() const noexcept;
42 /// Whether the file descriptor is valid.
43 bool IsValid() const noexcept;
44
45 /// If IsValid(), get file descriptor.
46 int GetFd() const;
47
48 /// When you're done with fd, call Invalidate(). It unregisters the fd, after
49 /// that you have to call close(2) by yourself. After Invalidate() you may not
50 /// call Wait().
51 void Invalidate();
52
53 /// Setup fd and kind to wait for. After Reset() you may call Wait().
54 /// FdPoller does not take the ownership of `fd`, you still have to close `fd`
55 /// when you're done.
56 void Reset(int fd, Kind kind);
57
58 /// Wait for an event kind that was passed in the latest Reset() call. If the
59 /// operation (read/write) can already be handled, Wait() returns
60 /// immediately. You have to call Reset() at least once before call to
61 /// Wait().
62 [[nodiscard]] std::optional<Kind> Wait(Deadline);
63
64 private:
65 friend class impl::Direction;
66
67 enum class State : int {
68 kInvalid,
69 kReadyToUse,
70 kInUse, /// < used only in debug to detect invalid concurrent usage
71 };
72
73 void WakeupWaiters();
74 void SwitchStateToInUse();
75 void SwitchStateToReadyToUse();
76
77 struct Impl;
78 utils::FastPimpl<Impl, 144, 16> pimpl_;
79};
80
81} // namespace engine::io
82
83USERVER_NAMESPACE_END