xref: /aosp_15_r20/external/pigweed/pw_async2/examples/once_send_recv.cc (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 
15 // DOCSTAG: [pw_async2-examples-once-send-recv-manual]
16 #include "pw_async2/dispatcher.h"
17 #include "pw_async2/dispatcher_native.h"
18 #include "pw_async2/once_sender.h"
19 #include "pw_async2/poll.h"
20 #include "pw_log/log.h"
21 #include "pw_result/result.h"
22 
23 namespace {
24 
25 using ::pw::Result;
26 using ::pw::async2::Context;
27 using ::pw::async2::OnceReceiver;
28 using ::pw::async2::OnceSender;
29 using ::pw::async2::Pending;
30 using ::pw::async2::Poll;
31 using ::pw::async2::Ready;
32 using ::pw::async2::Task;
33 
34 class ReceiveAndLogValueTask : public Task {
35  public:
ReceiveAndLogValueTask(OnceReceiver<int> && int_receiver)36   ReceiveAndLogValueTask(OnceReceiver<int>&& int_receiver)
37       : int_receiver_(std::move(int_receiver)) {}
38 
39  private:
DoPend(Context & cx)40   Poll<> DoPend(Context& cx) override {
41     Poll<Result<int>> value = int_receiver_.Pend(cx);
42     if (value.IsPending()) {
43       return Pending();
44     }
45     if (!value->ok()) {
46       PW_LOG_ERROR(
47           "OnceSender was destroyed without sending a message! Outrageous :(");
48     }
49     PW_LOG_INFO("Got an int: %d", **value);
50     return Ready();
51   }
52 
53   OnceReceiver<int> int_receiver_;
54 };
55 
56 }  // namespace
57 // DOCSTAG: [pw_async2-examples-once-send-recv-manual]
58 
59 // DOCSTAG: [pw_async2-examples-once-send-recv-coro]
60 #include "pw_async2/coro.h"
61 #include "pw_async2/once_sender.h"
62 #include "pw_log/log.h"
63 #include "pw_result/result.h"
64 
65 namespace {
66 
67 using ::pw::OkStatus;
68 using ::pw::Status;
69 using ::pw::async2::Coro;
70 using ::pw::async2::CoroContext;
71 using ::pw::async2::OnceReceiver;
72 using ::pw::async2::OnceSender;
73 
ReceiveAndLogValue(CoroContext &,OnceReceiver<int> int_receiver)74 Coro<Status> ReceiveAndLogValue(CoroContext&, OnceReceiver<int> int_receiver) {
75   Result<int> value = co_await int_receiver;
76   if (!value.ok()) {
77     PW_LOG_ERROR(
78         "OnceSender was destroyed without sending a message! Outrageous :(");
79     co_return Status::Cancelled();
80   }
81   PW_LOG_INFO("Got an int: %d", *value);
82   co_return OkStatus();
83 }
84 
85 }  // namespace
86 // DOCSTAG: [pw_async2-examples-once-send-recv-coro]
87 
88 #include "pw_allocator/testing.h"
89 #include "pw_unit_test/framework.h"
90 
91 namespace {
92 
93 using ::pw::allocator::test::AllocatorForTest;
94 using ::pw::async2::Dispatcher;
95 using ::pw::async2::MakeOnceSenderAndReceiver;
96 
TEST(OnceSendRecv,ReceiveAndLogValueTask)97 TEST(OnceSendRecv, ReceiveAndLogValueTask) {
98   auto send_recv = MakeOnceSenderAndReceiver<int>();
99   ReceiveAndLogValueTask task(std::move(send_recv.second));
100   Dispatcher dispatcher;
101   dispatcher.Post(task);
102   EXPECT_TRUE(dispatcher.RunUntilStalled().IsPending());
103   send_recv.first.emplace(5);
104   EXPECT_TRUE(dispatcher.RunUntilStalled().IsReady());
105 }
106 
TEST(OnceSendRecv,ReceiveAndLogValueCoro)107 TEST(OnceSendRecv, ReceiveAndLogValueCoro) {
108   AllocatorForTest<256> alloc;
109   CoroContext coro_cx(alloc);
110   auto send_recv = MakeOnceSenderAndReceiver<int>();
111   auto coro = ReceiveAndLogValue(coro_cx, std::move(send_recv.second));
112   Dispatcher dispatcher;
113   EXPECT_TRUE(dispatcher.RunPendableUntilStalled(coro).IsPending());
114   send_recv.first.emplace(5);
115   EXPECT_EQ(dispatcher.RunPendableUntilStalled(coro), Ready(OkStatus()));
116 }
117 
118 }  // namespace
119