22#include "pw_assert/assert.h"
23#include "pw_clock_tree/internal/deferred_init.h"
24#include "pw_status/status.h"
25#include "pw_status/try.h"
26#include "pw_sync/interrupt_spin_lock.h"
27#include "pw_sync/mutex.h"
51 static constexpr bool kMayFail =
true;
133 uint32_t
IncRef() {
return ++ref_count_; }
137 PW_ASSERT(ref_count_ > 0);
152 uint32_t ref_count_ = 0;
165 static constexpr bool kMayBlock =
true;
166 static constexpr bool kMayFail =
true;
174 internal::DeferredInit<sync::Mutex> mutex_;
177 std::lock_guard lock(this->lock());
181 std::lock_guard lock(this->lock());
190 static constexpr bool kMayBlock =
false;
191 static constexpr bool kMayFail =
true;
200 std::lock_guard lock(this->lock());
204 std::lock_guard lock(this->lock());
213 static constexpr bool kMayFail =
false;
238template <
typename ElementType>
245 if (this->IncRef() > 1) {
251 Status status = this->DoEnable();
262 if (this->DecRef() > 0) {
268 Status status = this->DoDisable();
337template <
typename ElementType>
341 template <
typename SourceType>
343 static_assert(ElementType::kMayBlock || !SourceType::kMayBlock,
344 "Non-blocking element cannot depend on a blocking element");
346 ElementType::kMayFail || !SourceType::kMayFail,
347 "Non-failing element cannot depend on an element that might fail");
357 if (this->IncRef() > 1) {
369 Status status = this->DoEnable();
383 if (this->DecRef() > 0) {
389 if (
Status status = this->DoDisable(); !status.
ok()) {
404 template <
typename SourceType>
406 static_assert(ElementType::kMayBlock || !SourceType::kMayBlock,
407 "Non-blocking element cannot depend on a blocking element");
409 ElementType::kMayFail || !SourceType::kMayFail,
410 "Non-failing element cannot depend on an element that might fail");
414 Element& source() {
return *source_; }
454 virtual Status DoSetDivider(uint32_t divider) = 0;
469template <
typename ElementType>
475 template <
typename SourceType>
486 template <
typename T = ElementType>
487 typename std::enable_if_t<T::kMayFail, pw::Status>
SetDivider(
497 template <
typename T = ElementType>
511 std::lock_guard lock(this->lock());
512 return DoSetDividerLocked(
divider);
516 uint32_t old_divider = divider_;
518 if (this->ref_count() == 0) {
522 Status status = this->DoEnable();
525 divider_ = old_divider;
551 : element_(element) {}
561 if (element_ !=
nullptr) {
572 if (element_ !=
nullptr) {
constexpr bool ok() const
Definition: status.h:346
constexpr void IgnoreError() const
Definition: status.h:430
Definition: clock_tree.h:471
std::enable_if_t<!T::kMayFail, void > SetDivider(uint32_t divider)
Definition: clock_tree.h:498
Definition: clock_tree.h:434
Definition: clock_tree.h:239
Definition: clock_tree.h:296
Definition: clock_tree.h:286
Definition: clock_tree.h:338
Definition: clock_tree.h:163
Definition: clock_tree.h:45
Definition: clock_tree.h:211
Definition: clock_tree.h:188
Definition: clock_tree.h:548
Definition: interrupt_spin_lock.h:50
Status SetDivider(uint32_t divider)
Definition: clock_tree.h:445
pw::Status DoEnable() final
Function called when the clock tree element needs to get enabled.
Definition: clock_tree.h:298
void Release()
Release a reference to this clock tree element.
Definition: clock_tree.h:219
void Acquire()
Acquire a reference to this clock tree element.
Definition: clock_tree.h:216
pw::Status DoDisable() final
Definition: clock_tree.h:300
Status Acquire()
Definition: clock_tree.h:560
constexpr DependentElement(SourceType &source)
Create a dependent clock tree element that depends on source.
Definition: clock_tree.h:342
ClockSource< ElementBlocking > ClockSourceBlocking
Alias for a blocking clock source tree element.
Definition: clock_tree.h:277
Status DoAcquireLocked() final
Definition: clock_tree.h:244
std::enable_if_t< T::kMayFail, pw::Status > SetDivider(uint32_t divider)
Definition: clock_tree.h:487
virtual Status DoAcquireLocked()=0
Status Release()
Definition: clock_tree.h:79
static constexpr bool kMayBlock
Definition: clock_tree.h:50
Status DoRelease() final
Handle Release(), deferring locking the child class.
Definition: clock_tree.h:180
virtual Status DoReleaseLocked()=0
Status Acquire()
Definition: clock_tree.h:71
Element & element() const
Return the element implementing this interface.
Definition: clock_tree.h:448
Status DoReleaseLocked() final
Definition: clock_tree.h:261
virtual Status DoEnable()=0
Function called when the clock tree element needs to get enabled.
Status DoAcquire() final
Handle Acquire(), deferring locking the child class.
Definition: clock_tree.h:176
uint32_t IncRef()
Increment reference count and return incremented value.
Definition: clock_tree.h:133
pw::Status DoEnable() final
Function called when the clock tree element needs to get enabled.
Definition: clock_tree.h:288
void SetSource(SourceType &source)
Definition: clock_tree.h:405
constexpr ClockDividerElement(SourceType &source, uint32_t divider)
Definition: clock_tree.h:476
Status DoAcquire() final
Handle Acquire(), deferring locking the child class.
Definition: clock_tree.h:199
uint32_t divider() const
Get current divider value.
Definition: clock_tree.h:504
Status DoRelease() final
Handle Release(), deferring locking the child class.
Definition: clock_tree.h:203
virtual Status DoAcquire()=0
Handle Acquire(), deferring locking the child class.
uint32_t ref_count() const
Get reference count for this clock tree element.
Definition: clock_tree.h:57
pw::Status DoDisable() final
Definition: clock_tree.h:290
Status Release()
Definition: clock_tree.h:571
uint32_t DecRef()
Decrement reference count and return decremented value.
Definition: clock_tree.h:136
virtual Status DoRelease()=0
Handle Release(), deferring locking the child class.
Status DoAcquireLocked() final
Definition: clock_tree.h:356
Status AcquireWith(Element &element_with)
Definition: clock_tree.h:92
Status DoReleaseLocked() final
Definition: clock_tree.h:382
virtual Status DoDisable()
Definition: clock_tree.h:148
#define PW_TRY(expr)
Returns early if expr is a non-OK Status or Result.
Definition: try.h:27
constexpr Status OkStatus()
Definition: status.h:450
Clock tree management library.
Definition: clock_tree.h:30