Skip to content

Commit

Permalink
Document that calls are safe on nullptr Delegates, and remove redunda…
Browse files Browse the repository at this point in the history
…nt chesks from using code.
  • Loading branch information
dok-net committed Mar 8, 2023
1 parent eaa3fb5 commit b9a0f6e
Show file tree
Hide file tree
Showing 3 changed files with 68 additions and 6 deletions.
7 changes: 3 additions & 4 deletions src/SoftwareSerial.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -573,7 +573,7 @@ void IRAM_ATTR UARTBase::rxBitISR(UARTBase* self) {
// tick's LSB is repurposed for the level bit
if (!self->m_isrBuffer->push((curTick | 1U) ^ !level)) self->m_isrOverflow.store(true);
// Trigger rx callback only when receiver is starved
if (empty && self->m_rxHandler) self->m_rxHandler();
if (empty) self->m_rxHandler();
}

void IRAM_ATTR UARTBase::rxBitSyncISR(UARTBase* self) {
Expand All @@ -599,7 +599,7 @@ void IRAM_ATTR UARTBase::rxBitSyncISR(UARTBase* self) {
}
}
// Trigger rx callback only when receiver is starved
if (empty && self->m_rxHandler) self->m_rxHandler();
if (empty) self->m_rxHandler();
}

void UARTBase::onReceive(const Delegate<void(), void*>& handler) {
Expand All @@ -617,10 +617,9 @@ void UARTBase::onReceive(Delegate<void(), void*>&& handler) {
// The template member functions below must be in IRAM, but due to a bug GCC doesn't currently
// honor the attribute. Instead, it is possible to do explicit specialization and adorn
// these with the IRAM attribute:
// Delegate<>::operator bool, Delegate<>::operator (), circular_queue<>::available,
// Delegate<>::operator (), circular_queue<>::available,
// circular_queue<>::available_for_push, circular_queue<>::push_peek, circular_queue<>::push

template IRAM_ATTR delegate::detail::DelegateImpl<void*, void>::operator bool() const;
template void IRAM_ATTR delegate::detail::DelegateImpl<void*, void>::operator()() const;
template size_t IRAM_ATTR circular_queue<uint32_t, UARTBase*>::available() const;
template bool IRAM_ATTR circular_queue<uint32_t, UARTBase*>::push(uint32_t&&);
Expand Down
3 changes: 1 addition & 2 deletions src/SoftwareSerial.h
Original file line number Diff line number Diff line change
Expand Up @@ -435,10 +435,9 @@ using namespace EspSoftwareSerial;
// The template member functions below must be in IRAM, but due to a bug GCC doesn't currently
// honor the attribute. Instead, it is possible to do explicit specialization and adorn
// these with the IRAM attribute:
// Delegate<>::operator bool, Delegate<>::operator (), circular_queue<>::available,
// Delegate<>::operator (), circular_queue<>::available,
// circular_queue<>::available_for_push, circular_queue<>::push_peek, circular_queue<>::push

extern template delegate::detail::DelegateImpl<void*, void>::operator bool() const;
extern template void delegate::detail::DelegateImpl<void*, void>::operator()() const;
extern template size_t circular_queue<uint32_t, EspSoftwareSerial::UARTBase*>::available() const;
extern template bool circular_queue<uint32_t, EspSoftwareSerial::UARTBase*>::push(uint32_t&&);
Expand Down
64 changes: 64 additions & 0 deletions src/circular_queue/Delegate.h
Original file line number Diff line number Diff line change
Expand Up @@ -323,6 +323,14 @@ namespace delegate
}
}

/// Calling is safe without checking for nullptr.
/// If non-void, returns the default value.
/// In ISR context, where faults and exceptions must not
/// occurs, this saves the extra check for nullptr,
/// and allows the compiler to optimize out checks
/// in std::function which may not be ISR-safe or
/// cause linker errors, like l32r relocation errors
/// on the Xtensa ISA.
R IRAM_ATTR operator()(P... args) const
{
if (FP == kind)
Expand Down Expand Up @@ -538,6 +546,14 @@ namespace delegate
}
}

/// Calling is safe without checking for nullptr.
/// If non-void, returns the default value.
/// In ISR context, where faults and exceptions must not
/// occurs, this saves the extra check for nullptr,
/// and allows the compiler to optimize out checks
/// in std::function which may not be ISR-safe or
/// cause linker errors, like l32r relocation errors
/// on the Xtensa ISA.
R IRAM_ATTR operator()(P... args) const
{
if (FP == kind)
Expand Down Expand Up @@ -746,6 +762,14 @@ namespace delegate
}
}

/// Calling is safe without checking for nullptr.
/// If non-void, returns the default value.
/// In ISR context, where faults and exceptions must not
/// occurs, this saves the extra check for nullptr,
/// and allows the compiler to optimize out checks
/// in std::function which may not be ISR-safe or
/// cause linker errors, like l32r relocation errors
/// on the Xtensa ISA.
R IRAM_ATTR operator()(P... args) const
{
if (FP == kind)
Expand Down Expand Up @@ -846,6 +870,14 @@ namespace delegate
return reinterpret_cast<void*>(fn);
}

/// Calling is safe without checking for nullptr.
/// If non-void, returns the default value.
/// In ISR context, where faults and exceptions must not
/// occurs, this saves the extra check for nullptr,
/// and allows the compiler to optimize out checks
/// in std::function which may not be ISR-safe or
/// cause linker errors, like l32r relocation errors
/// on the Xtensa ISA.
inline R IRAM_ATTR operator()(P... args) const __attribute__((always_inline))
{
if (fn) return fn(std::forward<P...>(args...));
Expand Down Expand Up @@ -1127,6 +1159,14 @@ namespace delegate
}
}

/// Calling is safe without checking for nullptr.
/// If non-void, returns the default value.
/// In ISR context, where faults and exceptions must not
/// occurs, this saves the extra check for nullptr,
/// and allows the compiler to optimize out checks
/// in std::function which may not be ISR-safe or
/// cause linker errors, like l32r relocation errors
/// on the Xtensa ISA.
R IRAM_ATTR operator()() const
{
if (FP == kind)
Expand Down Expand Up @@ -1341,6 +1381,14 @@ namespace delegate
}
}

/// Calling is safe without checking for nullptr.
/// If non-void, returns the default value.
/// In ISR context, where faults and exceptions must not
/// occurs, this saves the extra check for nullptr,
/// and allows the compiler to optimize out checks
/// in std::function which may not be ISR-safe or
/// cause linker errors, like l32r relocation errors
/// on the Xtensa ISA.
R IRAM_ATTR operator()() const
{
if (FP == kind)
Expand Down Expand Up @@ -1549,6 +1597,14 @@ namespace delegate
}
}

/// Calling is safe without checking for nullptr.
/// If non-void, returns the default value.
/// In ISR context, where faults and exceptions must not
/// occurs, this saves the extra check for nullptr,
/// and allows the compiler to optimize out checks
/// in std::function which may not be ISR-safe or
/// cause linker errors, like l32r relocation errors
/// on the Xtensa ISA.
R IRAM_ATTR operator()() const
{
if (FP == kind)
Expand Down Expand Up @@ -1649,6 +1705,14 @@ namespace delegate
return nullptr;
}

/// Calling is safe without checking for nullptr.
/// If non-void, returns the default value.
/// In ISR context, where faults and exceptions must not
/// occurs, this saves the extra check for nullptr,
/// and allows the compiler to optimize out checks
/// in std::function which may not be ISR-safe or
/// cause linker errors, like l32r relocation errors
/// on the Xtensa ISA.
inline R IRAM_ATTR operator()() const __attribute__((always_inline))
{
if (fn) return fn();
Expand Down

0 comments on commit b9a0f6e

Please sign in to comment.