1 // Copyright 2023 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 #pragma once 16 #include <pw_async/dispatcher.h> 17 #include <pw_async/task.h> 18 19 #include "pw_bluetooth_sapphire/internal/host/common/assert.h" 20 21 namespace bt { 22 23 // SmartTask is a utility that wraps a pw::async::Task and adds features like 24 // cancelation upon destruction and state tracking. It is not thread safe, and 25 // should only be used on the same thread that the dispatcher is running on. 26 class SmartTask { 27 public: 28 explicit SmartTask(pw::async::Dispatcher& dispatcher, 29 pw::async::TaskFunction&& func = nullptr) dispatcher_(dispatcher)30 : dispatcher_(dispatcher), func_(std::move(func)) {} 31 ~SmartTask()32 ~SmartTask() { 33 if (pending_) { 34 PW_CHECK(Cancel()); 35 } 36 } 37 PostAt(pw::chrono::SystemClock::time_point time)38 void PostAt(pw::chrono::SystemClock::time_point time) { 39 pending_ = true; 40 dispatcher_.PostAt(task_, time); 41 } 42 PostAfter(pw::chrono::SystemClock::duration delay)43 void PostAfter(pw::chrono::SystemClock::duration delay) { 44 pending_ = true; 45 dispatcher_.PostAfter(task_, delay); 46 } 47 Post()48 void Post() { 49 pending_ = true; 50 dispatcher_.Post(task_); 51 } 52 Cancel()53 bool Cancel() { 54 pending_ = false; 55 return dispatcher_.Cancel(task_); 56 } 57 set_function(pw::async::TaskFunction && func)58 void set_function(pw::async::TaskFunction&& func) { func_ = std::move(func); } 59 is_pending()60 bool is_pending() const { return pending_; } 61 dispatcher()62 pw::async::Dispatcher& dispatcher() const { return dispatcher_; } 63 64 private: 65 pw::async::Dispatcher& dispatcher_; 66 pw::async::Task task_{[this](pw::async::Context& ctx, pw::Status status) { 67 pending_ = false; 68 if (func_) { 69 func_(ctx, status); 70 } 71 }}; 72 pw::async::TaskFunction func_ = nullptr; 73 bool pending_ = false; 74 }; 75 76 } // namespace bt 77