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