aboutsummaryrefslogtreecommitdiff
path: root/pw_async_basic
diff options
context:
space:
mode:
Diffstat (limited to 'pw_async_basic')
-rw-r--r--pw_async_basic/BUILD.bazel93
-rw-r--r--pw_async_basic/BUILD.gn25
-rw-r--r--pw_async_basic/CMakeLists.txt43
-rw-r--r--pw_async_basic/dispatcher.cc61
-rw-r--r--pw_async_basic/dispatcher_test.cc1
-rw-r--r--pw_async_basic/docs.rst16
-rw-r--r--pw_async_basic/fake_dispatcher.cc61
-rw-r--r--pw_async_basic/fake_dispatcher_fixture_test.cc23
-rw-r--r--pw_async_basic/heap_dispatcher_test.cc70
-rw-r--r--pw_async_basic/public/pw_async_basic/dispatcher.h9
-rw-r--r--pw_async_basic/public/pw_async_basic/fake_dispatcher.h17
-rw-r--r--pw_async_basic/public/pw_async_basic/task.h19
-rw-r--r--pw_async_basic/size_report/BUILD.bazel38
-rw-r--r--pw_async_basic/size_report/post_1_task.cc5
-rw-r--r--pw_async_basic/size_report/task.cc3
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;
}