diff options
Diffstat (limited to 'pw_async_basic')
-rw-r--r-- | pw_async_basic/BUILD.bazel | 93 | ||||
-rw-r--r-- | pw_async_basic/BUILD.gn | 25 | ||||
-rw-r--r-- | pw_async_basic/CMakeLists.txt | 43 | ||||
-rw-r--r-- | pw_async_basic/dispatcher.cc | 61 | ||||
-rw-r--r-- | pw_async_basic/dispatcher_test.cc | 1 | ||||
-rw-r--r-- | pw_async_basic/docs.rst | 16 | ||||
-rw-r--r-- | pw_async_basic/fake_dispatcher.cc | 61 | ||||
-rw-r--r-- | pw_async_basic/fake_dispatcher_fixture_test.cc | 23 | ||||
-rw-r--r-- | pw_async_basic/heap_dispatcher_test.cc | 70 | ||||
-rw-r--r-- | pw_async_basic/public/pw_async_basic/dispatcher.h | 9 | ||||
-rw-r--r-- | pw_async_basic/public/pw_async_basic/fake_dispatcher.h | 17 | ||||
-rw-r--r-- | pw_async_basic/public/pw_async_basic/task.h | 19 | ||||
-rw-r--r-- | pw_async_basic/size_report/BUILD.bazel | 38 | ||||
-rw-r--r-- | pw_async_basic/size_report/post_1_task.cc | 5 | ||||
-rw-r--r-- | pw_async_basic/size_report/task.cc | 3 |
15 files changed, 350 insertions, 134 deletions
diff --git a/pw_async_basic/BUILD.bazel b/pw_async_basic/BUILD.bazel index 8a1fb3aca..b490bc186 100644 --- a/pw_async_basic/BUILD.bazel +++ b/pw_async_basic/BUILD.bazel @@ -12,19 +12,88 @@ # License for the specific language governing permissions and limitations under # the License. -filegroup( - name = "pw_async_files", - srcs = [ - "dispatcher.cc", - "dispatcher_test.cc", - "fake_dispatcher.cc", - "fake_dispatcher_fixture_test.cc", - "public/pw_async_basic/dispatcher.h", - "public/pw_async_basic/fake_dispatcher.h", +load( + "//pw_build:pigweed.bzl", + "pw_cc_library", + "pw_cc_test", +) + +package(default_visibility = ["//visibility:public"]) + +licenses(["notice"]) + +# Backend for //pw_async:task +pw_cc_library( + name = "task", + hdrs = [ "public/pw_async_basic/task.h", - "public_overrides/pw_async_backend/fake_dispatcher.h", "public_overrides/pw_async_backend/task.h", - "size_report/post_1_task.cc", - "size_report/task.cc", + ], + includes = [ + "public", + "public_overrides", + ], + deps = [ + "//pw_async:task_facade", + "//pw_containers:intrusive_list", + ], +) + +# Backend for //pw_async:fake_dispatcher +pw_cc_library( + name = "fake_dispatcher", + srcs = ["fake_dispatcher.cc"], + hdrs = [ + "public/pw_async_basic/fake_dispatcher.h", + "public_overrides/pw_async_backend/fake_dispatcher.h", + ], + includes = [ + "public", + "public_override", + ], + deps = [ + "//pw_async:fake_dispatcher_facade", + "//pw_async:task", + "//pw_log", + ], +) + +pw_cc_test( + name = "fake_dispatcher_fixture_test", + srcs = ["fake_dispatcher_fixture_test.cc"], + deps = ["//pw_async:fake_dispatcher_fixture"], +) + +pw_cc_library( + name = "dispatcher", + srcs = ["dispatcher.cc"], + hdrs = ["public/pw_async_basic/dispatcher.h"], + includes = ["public"], + deps = [ + "//pw_async:dispatcher", + "//pw_async:task", + "//pw_containers:intrusive_list", + "//pw_sync:interrupt_spin_lock", + "//pw_sync:timed_thread_notification", + "//pw_thread:thread_core", + ], +) + +pw_cc_test( + name = "dispatcher_test", + srcs = ["dispatcher_test.cc"], + deps = [ + ":dispatcher", + "//pw_log", + "//pw_thread:thread", + ], +) + +pw_cc_test( + name = "heap_dispatcher_test", + srcs = ["heap_dispatcher_test.cc"], + deps = [ + "//pw_async:fake_dispatcher_fixture", + "//pw_async:heap_dispatcher", ], ) diff --git a/pw_async_basic/BUILD.gn b/pw_async_basic/BUILD.gn index 9ccce5e85..e4fca69fb 100644 --- a/pw_async_basic/BUILD.gn +++ b/pw_async_basic/BUILD.gn @@ -17,6 +17,7 @@ import("//build_overrides/pigweed.gni") import("$dir_pw_async/async.gni") import("$dir_pw_async/fake_dispatcher_fixture.gni") import("$dir_pw_async/fake_dispatcher_test.gni") +import("$dir_pw_async/heap_dispatcher.gni") import("$dir_pw_bloat/bloat.gni") import("$dir_pw_build/target_types.gni") import("$dir_pw_chrono/backend.gni") @@ -103,7 +104,6 @@ pw_source_set("dispatcher") { "$dir_pw_sync:interrupt_spin_lock", "$dir_pw_sync:timed_thread_notification", "$dir_pw_thread:thread_core", - dir_pw_log, ] visibility = [ ":*", @@ -122,11 +122,34 @@ pw_test("dispatcher_test") { sources = [ "dispatcher_test.cc" ] } +# This target cannot be labeled "heap_dispatcher" or else the outpath Ninja uses +# for heap_dispatcher.cc will collide with $dir_pw_async:heap_dispatcher. +pw_async_heap_dispatcher_source_set("heap_dispatcher_basic") { + task_backend = ":task" + visibility = [ ":*" ] +} + +group("heap_dispatcher") { + public_deps = [ ":heap_dispatcher_basic" ] + visibility = [ ":*" ] + pw_async_EXPERIMENTAL_MODULE_VISIBILITY +} + +pw_test("heap_dispatcher_test") { + enable_if = pw_chrono_SYSTEM_CLOCK_BACKEND != "" && + pw_thread_THREAD_BACKEND == "$dir_pw_thread_stl:thread" + sources = [ "heap_dispatcher_test.cc" ] + deps = [ + ":fake_dispatcher_fixture", + ":heap_dispatcher", + ] +} + pw_test_group("tests") { tests = [ ":dispatcher_test", ":fake_dispatcher_test", ":fake_dispatcher_fixture_test", + ":heap_dispatcher_test", ] } diff --git a/pw_async_basic/CMakeLists.txt b/pw_async_basic/CMakeLists.txt new file mode 100644 index 000000000..80d83fa8b --- /dev/null +++ b/pw_async_basic/CMakeLists.txt @@ -0,0 +1,43 @@ +# Copyright 2023 The Pigweed Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may not +# use this file except in compliance with the License. You may obtain a copy of +# the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations under +# the License. + +include($ENV{PW_ROOT}/pw_build/pigweed.cmake) + +pw_add_library(pw_async_basic.task_backend INTERFACE + HEADERS + public/pw_async_basic/task.h + public_overrides/pw_async_backend/task.h + PUBLIC_INCLUDES + public + public_overrides + PUBLIC_DEPS + pw_async.task.facade + pw_containers.intrusive_list +) + +pw_add_library(pw_async_basic.dispatcher_backend STATIC + HEADERS + public/pw_async_basic/dispatcher.h + SOURCES + dispatcher.cc + PUBLIC_INCLUDES + public + PUBLIC_DEPS + pw_async_basic.task_backend + pw_async.dispatcher.facade + pw_containers.intrusive_list + pw_sync.interrupt_spin_lock + pw_sync.timed_thread_notification + pw_thread.thread_core +) diff --git a/pw_async_basic/dispatcher.cc b/pw_async_basic/dispatcher.cc index 682ff4f6d..4b51956a1 100644 --- a/pw_async_basic/dispatcher.cc +++ b/pw_async_basic/dispatcher.cc @@ -13,16 +13,14 @@ // the License. #include "pw_async_basic/dispatcher.h" -#include "pw_assert/check.h" +#include <mutex> + #include "pw_chrono/system_clock.h" -#include "pw_log/log.h" using namespace std::chrono_literals; namespace pw::async { -const chrono::SystemClock::duration SLEEP_DURATION = 5s; - BasicDispatcher::~BasicDispatcher() { RequestStop(); lock_.lock(); @@ -70,13 +68,16 @@ void BasicDispatcher::MaybeSleep() { // Sleep until a notification is received or until the due time of the // next task. Notifications are sent when tasks are posted or 'stop' is // requested. - chrono::SystemClock::time_point wake_time = - task_queue_.empty() ? now() + SLEEP_DURATION - : task_queue_.front().due_time_; - + std::optional<chrono::SystemClock::time_point> wake_time = std::nullopt; + if (!task_queue_.empty()) { + wake_time = task_queue_.front().due_time_; + } lock_.unlock(); - PW_LOG_DEBUG("no task due; waiting for signal"); - timed_notification_.try_acquire_until(wake_time); + if (wake_time.has_value()) { + timed_notification_.try_acquire_until(*wake_time); + } else { + timed_notification_.acquire(); + } lock_.lock(); } } @@ -87,12 +88,7 @@ void BasicDispatcher::ExecuteDueTasks() { backend::NativeTask& task = task_queue_.front(); task_queue_.pop_front(); - if (task.interval().has_value()) { - PostTaskInternal(task, task.due_time_ + task.interval().value()); - } - lock_.unlock(); - PW_LOG_DEBUG("running task"); Context ctx{this, &task.task_}; task(ctx, OkStatus()); lock_.lock(); @@ -100,52 +96,27 @@ void BasicDispatcher::ExecuteDueTasks() { } void BasicDispatcher::RequestStop() { - std::lock_guard lock(lock_); - PW_LOG_DEBUG("stop requested"); - stop_requested_ = true; + { + std::lock_guard lock(lock_); + stop_requested_ = true; + } timed_notification_.release(); } void BasicDispatcher::DrainTaskQueue() { - PW_LOG_DEBUG("draining task queue"); while (!task_queue_.empty()) { backend::NativeTask& task = task_queue_.front(); task_queue_.pop_front(); lock_.unlock(); - PW_LOG_DEBUG("running cancelled task"); Context ctx{this, &task.task_}; task(ctx, Status::Cancelled()); lock_.lock(); } } -void BasicDispatcher::Post(Task& task) { PostAt(task, now()); } - -void BasicDispatcher::PostAfter(Task& task, - chrono::SystemClock::duration delay) { - PostAt(task, now() + delay); -} - void BasicDispatcher::PostAt(Task& task, chrono::SystemClock::time_point time) { - lock_.lock(); - PW_LOG_DEBUG("posting task"); PostTaskInternal(task.native_type(), time); - lock_.unlock(); -} - -void BasicDispatcher::PostPeriodic(Task& task, - chrono::SystemClock::duration interval) { - PostPeriodicAt(task, interval, now()); -} - -void BasicDispatcher::PostPeriodicAt( - Task& task, - chrono::SystemClock::duration interval, - chrono::SystemClock::time_point start_time) { - PW_DCHECK(interval != chrono::SystemClock::duration::zero()); - task.native_type().set_interval(interval); - PostAt(task, start_time); } bool BasicDispatcher::Cancel(Task& task) { @@ -155,6 +126,7 @@ bool BasicDispatcher::Cancel(Task& task) { void BasicDispatcher::PostTaskInternal( backend::NativeTask& task, chrono::SystemClock::time_point time_due) { + lock_.lock(); task.due_time_ = time_due; auto it_front = task_queue_.begin(); auto it_behind = task_queue_.before_begin(); @@ -163,6 +135,7 @@ void BasicDispatcher::PostTaskInternal( ++it_behind; } task_queue_.insert_after(it_behind, task); + lock_.unlock(); timed_notification_.release(); } diff --git a/pw_async_basic/dispatcher_test.cc b/pw_async_basic/dispatcher_test.cc index 3f72bbb4f..bd4108e5e 100644 --- a/pw_async_basic/dispatcher_test.cc +++ b/pw_async_basic/dispatcher_test.cc @@ -14,6 +14,7 @@ #include "pw_async_basic/dispatcher.h" #include "gtest/gtest.h" +#include "pw_chrono/system_clock.h" #include "pw_log/log.h" #include "pw_sync/thread_notification.h" #include "pw_thread/thread.h" diff --git a/pw_async_basic/docs.rst b/pw_async_basic/docs.rst index 0363a2683..76924074a 100644 --- a/pw_async_basic/docs.rst +++ b/pw_async_basic/docs.rst @@ -20,20 +20,20 @@ First, set the following GN variables: .. code-block:: - pw_async_TASK_BACKEND="$dir_pw_async_basic:task" - pw_async_FAKE_DISPATCHER_BACKEND="$dir_pw_async_basic:fake_dispatcher" + pw_async_TASK_BACKEND="$dir_pw_async_basic:task" + pw_async_FAKE_DISPATCHER_BACKEND="$dir_pw_async_basic:fake_dispatcher" Next, create a target that depends on ``//pw_async_basic:dispatcher``: .. code-block:: - pw_executable("hello_world") { - sources = [ "hello_world.cc" ] - deps = [ - "//pw_async_basic:dispatcher", - ] - } + pw_executable("hello_world") { + sources = [ "hello_world.cc" ] + deps = [ + "//pw_async_basic:dispatcher", + ] + } Next, construct and use a ``BasicDispatcher``. diff --git a/pw_async_basic/fake_dispatcher.cc b/pw_async_basic/fake_dispatcher.cc index cbba89e98..6e649faee 100644 --- a/pw_async_basic/fake_dispatcher.cc +++ b/pw_async_basic/fake_dispatcher.cc @@ -29,47 +29,50 @@ NativeFakeDispatcher::~NativeFakeDispatcher() { DrainTaskQueue(); } -void NativeFakeDispatcher::RunUntilIdle() { - ExecuteDueTasks(); +bool NativeFakeDispatcher::RunUntilIdle() { + bool tasks_ran = ExecuteDueTasks(); if (stop_requested_) { - DrainTaskQueue(); + tasks_ran |= DrainTaskQueue(); } + return tasks_ran; } -void NativeFakeDispatcher::RunUntil(chrono::SystemClock::time_point end_time) { +bool NativeFakeDispatcher::RunUntil(chrono::SystemClock::time_point end_time) { + bool tasks_ran = false; while (!task_queue_.empty() && task_queue_.front().due_time() <= end_time && !stop_requested_) { now_ = task_queue_.front().due_time(); - ExecuteDueTasks(); + tasks_ran |= ExecuteDueTasks(); } if (stop_requested_) { - DrainTaskQueue(); - return; + tasks_ran |= DrainTaskQueue(); + return tasks_ran; } if (now_ < end_time) { now_ = end_time; } + return tasks_ran; } -void NativeFakeDispatcher::RunFor(chrono::SystemClock::duration duration) { - RunUntil(now() + duration); +bool NativeFakeDispatcher::RunFor(chrono::SystemClock::duration duration) { + return RunUntil(now() + duration); } -void NativeFakeDispatcher::ExecuteDueTasks() { +bool NativeFakeDispatcher::ExecuteDueTasks() { + bool task_ran = false; while (!task_queue_.empty() && task_queue_.front().due_time() <= now() && !stop_requested_) { ::pw::async::backend::NativeTask& task = task_queue_.front(); task_queue_.pop_front(); - if (task.interval().has_value()) { - PostTaskInternal(task, task.due_time() + task.interval().value()); - } - Context ctx{&dispatcher_, &task.task_}; task(ctx, OkStatus()); + + task_ran = true; } + return task_ran; } void NativeFakeDispatcher::RequestStop() { @@ -77,7 +80,8 @@ void NativeFakeDispatcher::RequestStop() { stop_requested_ = true; } -void NativeFakeDispatcher::DrainTaskQueue() { +bool NativeFakeDispatcher::DrainTaskQueue() { + bool task_ran = false; while (!task_queue_.empty()) { ::pw::async::backend::NativeTask& task = task_queue_.front(); task_queue_.pop_front(); @@ -85,7 +89,10 @@ void NativeFakeDispatcher::DrainTaskQueue() { PW_LOG_DEBUG("running cancelled task"); Context ctx{&dispatcher_, &task.task_}; task(ctx, Status::Cancelled()); + + task_ran = true; } + return task_ran; } void NativeFakeDispatcher::Post(Task& task) { PostAt(task, now()); } @@ -101,19 +108,6 @@ void NativeFakeDispatcher::PostAt(Task& task, PostTaskInternal(task.native_type(), time); } -void NativeFakeDispatcher::PostPeriodic( - Task& task, chrono::SystemClock::duration interval) { - PostPeriodicAt(task, interval, now()); -} - -void NativeFakeDispatcher::PostPeriodicAt( - Task& task, - chrono::SystemClock::duration interval, - chrono::SystemClock::time_point start_time) { - task.native_type().set_interval(interval); - PostAt(task, start_time); -} - bool NativeFakeDispatcher::Cancel(Task& task) { return task_queue_.remove(task.native_type()); } @@ -121,10 +115,19 @@ bool NativeFakeDispatcher::Cancel(Task& task) { void NativeFakeDispatcher::PostTaskInternal( ::pw::async::backend::NativeTask& task, chrono::SystemClock::time_point time_due) { + if (!task.unlisted()) { + if (task.due_time() <= time_due) { + // No need to repost a task that was already queued to run. + return; + } + // The task needs its time updated, so we have to move it to + // a different part of the list. + task.unlist(); + } task.set_due_time(time_due); auto it_front = task_queue_.begin(); auto it_behind = task_queue_.before_begin(); - while (it_front != task_queue_.end() && time_due > it_front->due_time()) { + while (it_front != task_queue_.end() && time_due >= it_front->due_time()) { ++it_front; ++it_behind; } diff --git a/pw_async_basic/fake_dispatcher_fixture_test.cc b/pw_async_basic/fake_dispatcher_fixture_test.cc index 5262c3438..dfdf9b393 100644 --- a/pw_async_basic/fake_dispatcher_fixture_test.cc +++ b/pw_async_basic/fake_dispatcher_fixture_test.cc @@ -13,6 +13,8 @@ // the License. #include "pw_async/fake_dispatcher_fixture.h" +#include <chrono> + #include "gtest/gtest.h" namespace pw::async { @@ -20,7 +22,7 @@ namespace { using FakeDispatcherFixture = test::FakeDispatcherFixture; -TEST_F(FakeDispatcherFixture, PostTasks) { +TEST_F(FakeDispatcherFixture, PostTasksAndStop) { int count = 0; auto inc_count = [&count](Context& /*c*/, Status /*status*/) { ++count; }; @@ -28,8 +30,25 @@ TEST_F(FakeDispatcherFixture, PostTasks) { dispatcher().Post(task); ASSERT_EQ(count, 0); - RunUntilIdle(); + EXPECT_TRUE(RunUntilIdle()); ASSERT_EQ(count, 1); + EXPECT_FALSE(RunUntilIdle()); + + dispatcher().Post(task); + EXPECT_TRUE(RunUntil(dispatcher().now())); + ASSERT_EQ(count, 2); + EXPECT_FALSE(RunUntilIdle()); + + dispatcher().Post(task); + EXPECT_TRUE(RunFor(std::chrono::seconds(1))); + ASSERT_EQ(count, 3); + EXPECT_FALSE(RunUntilIdle()); + + dispatcher().PostAfter(task, std::chrono::minutes(1)); + dispatcher().RequestStop(); + ASSERT_EQ(count, 3); + EXPECT_TRUE(RunUntilIdle()); + ASSERT_EQ(count, 4); } } // namespace diff --git a/pw_async_basic/heap_dispatcher_test.cc b/pw_async_basic/heap_dispatcher_test.cc new file mode 100644 index 000000000..3c744971d --- /dev/null +++ b/pw_async_basic/heap_dispatcher_test.cc @@ -0,0 +1,70 @@ +// Copyright 2023 The Pigweed Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy of +// the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +#include "pw_async/heap_dispatcher.h" + +#include "gtest/gtest.h" +#include "pw_async/fake_dispatcher_fixture.h" + +using namespace std::chrono_literals; + +namespace pw::async { +namespace { + +using HeapDispatcherTest = test::FakeDispatcherFixture; + +class DestructionChecker { + public: + DestructionChecker(bool* flag) : flag_(flag) {} + DestructionChecker(DestructionChecker&& other) { + flag_ = other.flag_; + other.flag_ = nullptr; + } + ~DestructionChecker() { + if (flag_) { + *flag_ = true; + } + } + + private: + bool* flag_; +}; + +TEST_F(HeapDispatcherTest, RunUntilIdleRunsPostedTask) { + HeapDispatcher heap_dispatcher(dispatcher()); + + int count = 0; + Status status = heap_dispatcher.Post( + [&count](Context& /*ctx*/, Status /*status*/) { ++count; }); + EXPECT_TRUE(status.ok()); + ASSERT_EQ(count, 0); + RunUntilIdle(); + ASSERT_EQ(count, 1); +} + +TEST_F(HeapDispatcherTest, TaskFunctionIsDestroyedAfterBeingCalled) { + HeapDispatcher heap_dispatcher(dispatcher()); + + // Test that the lambda is destroyed after being called. + bool flag = false; + Status status = + heap_dispatcher.Post([checker = DestructionChecker(&flag)]( + Context& /*ctx*/, Status /*status*/) {}); + EXPECT_TRUE(status.ok()); + EXPECT_FALSE(flag); + RunUntilIdle(); + EXPECT_TRUE(flag); +} + +} // namespace +} // namespace pw::async diff --git a/pw_async_basic/public/pw_async_basic/dispatcher.h b/pw_async_basic/public/pw_async_basic/dispatcher.h index 7050d6622..eb712ed63 100644 --- a/pw_async_basic/public/pw_async_basic/dispatcher.h +++ b/pw_async_basic/public/pw_async_basic/dispatcher.h @@ -53,14 +53,7 @@ class BasicDispatcher final : public Dispatcher, public thread::ThreadCore { void Run() override PW_LOCKS_EXCLUDED(lock_); // Dispatcher overrides: - void Post(Task& task) override; - void PostAfter(Task& task, chrono::SystemClock::duration delay) override; void PostAt(Task& task, chrono::SystemClock::time_point time) override; - void PostPeriodic(Task& task, - chrono::SystemClock::duration interval) override; - void PostPeriodicAt(Task& task, - chrono::SystemClock::duration interval, - chrono::SystemClock::time_point start_time) override; bool Cancel(Task& task) override PW_LOCKS_EXCLUDED(lock_); // VirtualSystemClock overrides: @@ -73,7 +66,7 @@ class BasicDispatcher final : public Dispatcher, public thread::ThreadCore { // |time_due|. void PostTaskInternal(backend::NativeTask& task, chrono::SystemClock::time_point time_due) - PW_EXCLUSIVE_LOCKS_REQUIRED(lock_); + PW_LOCKS_EXCLUDED(lock_); // If no tasks are due, sleep until a notification is received, the next task // comes due, or a timeout elapses; whichever occurs first. diff --git a/pw_async_basic/public/pw_async_basic/fake_dispatcher.h b/pw_async_basic/public/pw_async_basic/fake_dispatcher.h index 96fd7aae8..43d35038a 100644 --- a/pw_async_basic/public/pw_async_basic/fake_dispatcher.h +++ b/pw_async_basic/public/pw_async_basic/fake_dispatcher.h @@ -32,18 +32,13 @@ class NativeFakeDispatcher final { void PostAt(Task& task, chrono::SystemClock::time_point time); - void PostPeriodic(Task& task, chrono::SystemClock::duration interval); - void PostPeriodicAt(Task& task, - chrono::SystemClock::duration interval, - chrono::SystemClock::time_point start_time); - bool Cancel(Task& task); - void RunUntilIdle(); + bool RunUntilIdle(); - void RunUntil(chrono::SystemClock::time_point end_time); + bool RunUntil(chrono::SystemClock::time_point end_time); - void RunFor(chrono::SystemClock::duration duration); + bool RunFor(chrono::SystemClock::duration duration); chrono::SystemClock::time_point now() { return now_; } @@ -54,11 +49,13 @@ class NativeFakeDispatcher final { chrono::SystemClock::time_point time_due); // Dequeue and run each task that is due. - void ExecuteDueTasks(); + // Returns true iff any tasks were invoked during the run. + bool ExecuteDueTasks(); // Dequeue each task and run each TaskFunction with a PW_STATUS_CANCELLED // status. - void DrainTaskQueue(); + // Returns true iff any tasks were invoked during the run. + bool DrainTaskQueue(); Dispatcher& dispatcher_; bool stop_requested_ = false; diff --git a/pw_async_basic/public/pw_async_basic/task.h b/pw_async_basic/public/pw_async_basic/task.h index d83ea34ab..e2be508c6 100644 --- a/pw_async_basic/public/pw_async_basic/task.h +++ b/pw_async_basic/public/pw_async_basic/task.h @@ -13,7 +13,8 @@ // the License. #pragma once -#include "pw_async/internal/types.h" +#include "pw_async/context.h" +#include "pw_async/task_function.h" #include "pw_chrono/system_clock.h" #include "pw_containers/intrusive_list.h" @@ -43,19 +44,6 @@ class NativeTask final : public IntrusiveList<NativeTask>::Item { void set_due_time(chrono::SystemClock::time_point due_time) { due_time_ = due_time; } - std::optional<chrono::SystemClock::duration> interval() const { - if (interval_ == chrono::SystemClock::duration::zero()) { - return std::nullopt; - } - return interval_; - } - void set_interval(std::optional<chrono::SystemClock::duration> interval) { - if (!interval.has_value()) { - interval_ = chrono::SystemClock::duration::zero(); - return; - } - interval_ = *interval; - } TaskFunction func_ = nullptr; // task_ is placed after func_ to take advantage of the padding that would @@ -64,9 +52,6 @@ class NativeTask final : public IntrusiveList<NativeTask>::Item { // padding would be added here, which is just enough for a pointer. Task& task_; pw::chrono::SystemClock::time_point due_time_; - // A duration of 0 indicates that the task is not periodic. - chrono::SystemClock::duration interval_ = - chrono::SystemClock::duration::zero(); }; using NativeTaskHandle = NativeTask&; diff --git a/pw_async_basic/size_report/BUILD.bazel b/pw_async_basic/size_report/BUILD.bazel new file mode 100644 index 000000000..33c90988a --- /dev/null +++ b/pw_async_basic/size_report/BUILD.bazel @@ -0,0 +1,38 @@ +# Copyright 2023 The Pigweed Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may not +# use this file except in compliance with the License. You may obtain a copy of +# the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations under +# the License. + +load( + "//pw_build:pigweed.bzl", + "pw_cc_binary", +) + +licenses(["notice"]) + +pw_cc_binary( + name = "post_1_task", + srcs = ["post_1_task.cc"], + deps = [ + "//pw_async_basic:dispatcher", + "//pw_bloat:bloat_this_binary", + ], +) + +pw_cc_binary( + name = "task", + srcs = ["task.cc"], + deps = [ + "//pw_async:task", + "//pw_bloat:bloat_this_binary", + ], +) diff --git a/pw_async_basic/size_report/post_1_task.cc b/pw_async_basic/size_report/post_1_task.cc index ef6065b1c..c074cf184 100644 --- a/pw_async_basic/size_report/post_1_task.cc +++ b/pw_async_basic/size_report/post_1_task.cc @@ -19,8 +19,9 @@ int main() { pw::bloat::BloatThisBinary(); pw::async::BasicDispatcher dispatcher; - pw::async::Task task( - [](pw::async::Context& /*ctx*/) { printf("hello world\n"); }); + pw::async::Task task([](pw::async::Context& /*ctx*/, pw::Status /*status*/) { + printf("hello world\n"); + }); dispatcher.Post(task); dispatcher.Run(); return 0; diff --git a/pw_async_basic/size_report/task.cc b/pw_async_basic/size_report/task.cc index d149346fe..d35c766e0 100644 --- a/pw_async_basic/size_report/task.cc +++ b/pw_async_basic/size_report/task.cc @@ -18,6 +18,7 @@ int main() { pw::bloat::BloatThisBinary(); - pw::async::Task task([](pw::async::Context& /*ctx*/) {}); + pw::async::Task task( + [](pw::async::Context& /*ctx*/, pw::Status /*status*/) {}); return 0; } |