• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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-count]
16 #define PW_LOG_MODULE_NAME "ASYNC_COUNTER"
17 
18 #include "pw_allocator/libc_allocator.h"
19 #include "pw_async2/allocate_task.h"
20 #include "pw_async2/coro.h"
21 #include "pw_async2/coro_or_else_task.h"
22 #include "pw_async2/dispatcher.h"
23 #include "pw_async2/system_time_provider.h"
24 #include "pw_chrono/system_clock.h"
25 #include "pw_log/log.h"
26 #include "pw_result/result.h"
27 #include "pw_status/status.h"
28 
29 using ::pw::Allocator;
30 using ::pw::OkStatus;
31 using ::pw::Result;
32 using ::pw::Status;
33 using ::pw::allocator::GetLibCAllocator;
34 using ::pw::async2::AllocateTask;
35 using ::pw::async2::Coro;
36 using ::pw::async2::CoroContext;
37 using ::pw::async2::CoroOrElseTask;
38 using ::pw::async2::Dispatcher;
39 using ::pw::async2::GetSystemTimeProvider;
40 using ::pw::async2::Task;
41 using ::pw::async2::TimeProvider;
42 using ::pw::chrono::SystemClock;
43 using ::std::chrono_literals::operator""ms;
44 
45 namespace {
46 
47 class Counter {
48  public:
49   // examples-constructor-start
Counter(Dispatcher & dispatcher,Allocator & allocator,TimeProvider<SystemClock> & time)50   Counter(Dispatcher& dispatcher,
51           Allocator& allocator,
52           TimeProvider<SystemClock>& time)
53       : dispatcher_(&dispatcher), allocator_(&allocator), time_(&time) {}
54   // examples-constructor-end
55 
56   // examples-task-start
57   // Posts a new asynchronous task which will count up to `times`, one count
58   // per `period`.
StartCounting(SystemClock::duration period,int times)59   void StartCounting(SystemClock::duration period, int times) {
60     CoroContext coro_cx(*allocator_);
61     Coro<Status> coro = CountCoro(coro_cx, period, times);
62     Task* new_task =
63         AllocateTask<CoroOrElseTask>(*allocator_, std::move(coro), [](Status) {
64           PW_LOG_ERROR("Counter coroutine failed to allocate.");
65         });
66 
67     // The newly allocated task will be free'd by the dispatcher
68     // upon completion.
69     dispatcher_->Post(*new_task);
70   }
71   // examples-task-end
72 
73  private:
74   // Asynchronous counter implementation.
CountCoro(CoroContext &,SystemClock::duration period,int times)75   Coro<Status> CountCoro(CoroContext&,
76                          SystemClock::duration period,
77                          int times) {
78     PW_LOG_INFO("Counting to %i", times);
79     for (int i = 1; i <= times; ++i) {
80       co_await time_->WaitFor(period);
81       PW_LOG_INFO("%i of %i", i, times);
82     }
83     co_return OkStatus();
84   }
85 
86   Dispatcher* dispatcher_;
87   Allocator* allocator_;
88   TimeProvider<SystemClock>* time_;
89 };
90 
91 }  // namespace
92 
main()93 int main() {
94   Allocator& alloc = GetLibCAllocator();
95   TimeProvider<SystemClock>& time = GetSystemTimeProvider();
96   Dispatcher dispatcher;
97 
98   Counter counter(dispatcher, alloc, time);
99   counter.StartCounting(/*period=*/500ms, /*times=*/5);
100 
101   dispatcher.RunToCompletion();
102 }
103 // DOCSTAG: [pw_async2-examples-count]
104