xref: /aosp_15_r20/external/pigweed/pw_channel/public/pw_channel/epoll_channel.h (revision 61c4878ac05f98d0ceed94b57d316916de578985)
1 // Copyright 2024 The Pigweed Authors
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License"); you may not
4 // use this file except in compliance with the License. You may obtain a copy of
5 // the License at
6 //
7 //     https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11 // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12 // License for the specific language governing permissions and limitations under
13 // the License.
14 #pragma once
15 
16 #include <cstdint>
17 #include <optional>
18 
19 #include "pw_async2/dispatcher.h"
20 #include "pw_async2/poll.h"
21 #include "pw_channel/channel.h"
22 #include "pw_multibuf/allocator.h"
23 #include "pw_multibuf/multibuf.h"
24 
25 namespace pw::channel {
26 
27 /// @defgroup pw_channel_epoll
28 /// @{
29 
30 /// Channel implementation which writes to and reads from a file descriptor,
31 /// backed by Linux's epoll notification system.
32 ///
33 /// This channel depends on APIs provided by the EpollDispatcher and cannot be
34 /// used with any other dispatcher backend.
35 ///
36 /// An instantiated EpollChannel takes ownership of the file descriptor it is
37 /// given, and will close it if the channel is closed or destroyed. Users should
38 /// not close a channel's file descriptor from outside.
39 class EpollChannel : public Implement<ByteReaderWriter> {
40  public:
EpollChannel(int channel_fd,async2::Dispatcher & dispatcher,multibuf::MultiBufAllocator & allocator)41   EpollChannel(int channel_fd,
42                async2::Dispatcher& dispatcher,
43                multibuf::MultiBufAllocator& allocator)
44       : channel_fd_(channel_fd),
45         ready_to_write_(false),
46         dispatcher_(&dispatcher),
47         write_alloc_future_(allocator) {
48     Register();
49   }
50 
~EpollChannel()51   ~EpollChannel() override { Cleanup(); }
52 
53   EpollChannel(const EpollChannel&) = delete;
54   EpollChannel& operator=(const EpollChannel&) = delete;
55 
56   EpollChannel(EpollChannel&&) = default;
57   EpollChannel& operator=(EpollChannel&&) = default;
58 
59  private:
60   static constexpr size_t kMinimumReadSize = 64;
61   static constexpr size_t kDesiredReadSize = 1024;
62 
63   void Register();
64 
65   async2::Poll<Result<multibuf::MultiBuf>> DoPendRead(
66       async2::Context& cx) override;
67 
68   async2::Poll<Status> DoPendReadyToWrite(async2::Context& cx) final;
69 
DoPendAllocateWriteBuffer(async2::Context & cx,size_t min_bytes)70   async2::Poll<std::optional<multibuf::MultiBuf>> DoPendAllocateWriteBuffer(
71       async2::Context& cx, size_t min_bytes) final {
72     write_alloc_future_.SetDesiredSize(min_bytes);
73     return write_alloc_future_.Pend(cx);
74   }
75 
76   Status DoStageWrite(multibuf::MultiBuf&& data) final;
77 
DoPendWrite(async2::Context &)78   async2::Poll<Status> DoPendWrite(async2::Context&) final {
79     return OkStatus();
80   }
81 
DoPendClose(async2::Context &)82   async2::Poll<Status> DoPendClose(async2::Context&) final {
83     Cleanup();
84     return async2::Ready(OkStatus());
85   }
86 
set_closed()87   void set_closed() {
88     set_read_closed();
89     set_write_closed();
90   }
91 
92   void Cleanup();
93 
94   int channel_fd_;
95   bool ready_to_write_;
96 
97   async2::Dispatcher* dispatcher_;
98   multibuf::MultiBufAllocationFuture write_alloc_future_;
99   async2::Waker waker_;
100 };
101 
102 /// @}
103 
104 }  // namespace pw::channel
105