ion 0.12.0
Atomic concurrency support library
Loading...
Searching...
No Matches
Signals

Thread safe atomic signals. More...

Files

file  signal.hpp
 ion::{SignalSource, SignalToken} and algorithms
 

Classes

class  ion::SignalSource< T >
 Atomic signal source. More...
 
class  ion::SignalToken< T >
 Signal token that has an associated SignalSource and last known value. More...
 
struct  ion::Status< T >
 Represents signal source previous (old) and current (new) value. More...
 
struct  ion::WaitAnyResult< T1, T2 >
 Represents wait result from one of multiple possible signals. More...
 
struct  ion::StatusTag
 Select algorithm overload that returns signal status. More...
 
struct  ion::DifferenceTag
 Select algorithm overload that returns signal difference. More...
 

Functions

template<class T, class UnaryOperation>
auto ion::CompareExchangeTransform (SignalSource< T > &signal, UnaryOperation op) noexcept -> T
 Performs atomic compare-exchange transformation of signal value.
 
template<class T>
constexpr auto ion::operator== (SignalToken< T > const &lhs, SignalToken< T > const &rhs) noexcept -> bool
 Equality comparison.
 
template<class T>
constexpr auto ion::operator!= (SignalToken< T > const &lhs, SignalToken< T > const &rhs) noexcept -> bool
 Inequality comparison.
 
template<class T, class UnaryOperation>
auto CompareExchangeTransform (SignalSource< T > &signal, UnaryOperation op) noexcept -> T
 Performs atomic compare-exchange transformation of signal value.
 
template<class T>
constexpr auto operator== (SignalToken< T > const &lhs, SignalToken< T > const &rhs) noexcept -> bool
 Equality comparison.
 
template<class T>
constexpr auto operator!= (SignalToken< T > const &lhs, SignalToken< T > const &rhs) noexcept -> bool
 Inequality comparison.
 

Tag-invoke types

constexpr StatusTag ion::status_tag {}
 Constant instance of StatusTag.
 
constexpr DifferenceTag ion::difference_tag {}
 Constant instance of DifferenceTag.
 

Wait and yield current signal value.

template<class T>
auto ion::Wait (SignalToken< T > &token) noexcept -> T
 Wait until signal source changes and return current value.
 
template<class T, class Predicate>
auto ion::Wait (SignalToken< T > &token, Predicate &&stop_waiting) noexcept -> T
 Wait with predicate.
 
template<class T>
auto Wait (SignalToken< T > &token) noexcept -> T
 Wait until signal source changes and return current value.
 
template<class T, class Predicate>
auto Wait (SignalToken< T > &token, Predicate &&stop_waiting) noexcept -> T
 Wait with predicate.
 

Wait and yield Status<T>.

template<class T>
auto ion::Wait (StatusTag, SignalToken< T > &token) noexcept -> Status< T >
 Wait until signal source changes and return current and previous values.
 
template<class T, class Predicate>
auto ion::Wait (StatusTag, SignalToken< T > &token, Predicate &&stop_waiting) noexcept -> Status< T >
 Wait with predicate.
 
template<class T>
auto Wait (StatusTag, SignalToken< T > &token) noexcept -> Status< T >
 Wait until signal source changes and return current and previous values.
 
template<class T, class Predicate>
auto Wait (StatusTag, SignalToken< T > &token, Predicate &&stop_waiting) noexcept -> Status< T >
 Wait with predicate.
 

Wait and yield changes since last.

template<class T>
auto ion::Wait (DifferenceTag, SignalToken< T > &token) noexcept -> T
 Wait until signal source changes and return difference (current - previous) value.
 
template<class T, class Predicate>
auto ion::Wait (DifferenceTag, SignalToken< T > &token, Predicate &&stop_waiting) noexcept -> T
 Wait until signal source changes and return difference (current - previous) value.
 
template<class T>
auto Wait (DifferenceTag, SignalToken< T > &token) noexcept -> T
 Wait until signal source changes and return difference (current - previous) value.
 
template<class T, class Predicate>
auto Wait (DifferenceTag, SignalToken< T > &token, Predicate &&stop_waiting) noexcept -> T
 Wait until signal source changes and return difference (current - previous) value.
 

Wait for either of two signals.

Effects Load and compare each of the signals with previous value.

The first one to change will be recorded in the WaitAnyResult::index. Depending on the selected overload the result of WaitAnyResult::result is either the current, difference or the Status containing both previous and current value.

template<class T1, class T2>
auto ion::WaitAny (SignalToken< T1 > &token1, SignalToken< T2 > &token2) noexcept -> WaitAnyResult< T1, T2 >
 Wait for either of two signals to change.
 
template<class T1, class T2>
auto ion::WaitAny (StatusTag, SignalToken< T1 > &token1, SignalToken< T2 > &token2) noexcept -> WaitAnyResult< Status< T1 >, Status< T2 > >
 Wait for either of two signals to change.
 
template<class T1, class T2>
auto ion::WaitAny (DifferenceTag, SignalToken< T1 > &token1, SignalToken< T2 > &token2) noexcept -> WaitAnyResult< T1, T2 >
 Wait for either of two signals to change.
 
template<class T1, class T2>
auto WaitAny (SignalToken< T1 > &token1, SignalToken< T2 > &token2) noexcept -> WaitAnyResult< T1, T2 >
 Wait for either of two signals to change.
 
template<class T1, class T2>
auto WaitAny (StatusTag, SignalToken< T1 > &token1, SignalToken< T2 > &token2) noexcept -> WaitAnyResult< Status< T1 >, Status< T2 > >
 Wait for either of two signals to change.
 
template<class T1, class T2>
auto WaitAny (DifferenceTag, SignalToken< T1 > &token1, SignalToken< T2 > &token2) noexcept -> WaitAnyResult< T1, T2 >
 Wait for either of two signals to change.
 

Detailed Description

Thread safe atomic signals.

#include <cstdint>
#include <thread>
#include <ion/signal.hpp>
int main() {
auto source = ion::SignalSource<int>();
// To avoid race-condition between storing new signal value and what token
// initializes to we create the token in the main thread.
std::thread thread([token=ion::SignalToken<int>(&source)]() mutable {
auto current = Wait(token);
std::cout << "Got signal: " << current << std::endl;
});
// Update signal
source.Store(42);
thread.join();
}
Atomic signal source.
Definition signal.hpp:66
Signal token that has an associated SignalSource and last known value.
Definition signal.hpp:187
ion::{SignalSource, SignalToken} and algorithms

Function Documentation

◆ CompareExchangeTransform() [1/2]

template<class T, class UnaryOperation>
auto CompareExchangeTransform ( SignalSource< T > & signal,
UnaryOperation op ) -> T
related

Performs atomic compare-exchange transformation of signal value.

Note
Provided transform operation op will potentially be invoked any number of times - until underlying compare exchange operation is successful.

Example where S::second is reset to 0 without clobbering S::first - even if signal is modified from multiple threads.

struct S {
std::uint32_t first;
std::uint32_t second;
};
void ResetSecond(ion::SignalSource<S>& signal) {
CompareExchangeTransform(s, [](S value) noexcept {
// Leave value.first as is.
value.second = 0u;
return value;
});
}
auto CompareExchangeTransform(SignalSource< T > &signal, UnaryOperation op) noexcept -> T
Performs atomic compare-exchange transformation of signal value.
Parameters
signalSignal to transform value on.
optransform operation.
Returns
Transformed value that was successfully stored in signal.
Template Parameters
UnaryOperationNoexcept callable invocable as T callable(T const& t) noexcept, (which means T callable(T t) noexcept is also valid).

◆ CompareExchangeTransform() [2/2]

template<class T, class UnaryOperation>
auto CompareExchangeTransform ( SignalSource< T > & signal,
UnaryOperation op ) -> T
related

Performs atomic compare-exchange transformation of signal value.

Note
Provided transform operation op will potentially be invoked any number of times - until underlying compare exchange operation is successful.

Example where S::second is reset to 0 without clobbering S::first - even if signal is modified from multiple threads.

struct S {
std::uint32_t first;
std::uint32_t second;
};
void ResetSecond(ion::SignalSource<S>& signal) {
CompareExchangeTransform(s, [](S value) noexcept {
// Leave value.first as is.
value.second = 0u;
return value;
});
}
Parameters
signalSignal to transform value on.
optransform operation.
Returns
Transformed value that was successfully stored in signal.
Template Parameters
UnaryOperationNoexcept callable invocable as T callable(T const& t) noexcept, (which means T callable(T t) noexcept is also valid).

◆ operator!=() [1/2]

template<class T>
auto operator!= ( SignalToken< T > const & lhs,
SignalToken< T > const & rhs ) -> bool
nodiscardconstexprnoexcept

Inequality comparison.

Parameters
lhsLeft hand side of comparison.
rhsRIght hand side of comparison.
Returns
false if both lhs and rhs are associated with the same signal source and have the same last value.
true otherwise.
Template Parameters
TValueType that must provide bool operator==(T const&, T const&) noexcept.

◆ operator!=() [2/2]

template<class T>
auto operator!= ( SignalToken< T > const & lhs,
SignalToken< T > const & rhs ) -> bool
related

Inequality comparison.

Parameters
lhsLeft hand side of comparison.
rhsRIght hand side of comparison.
Returns
false if both lhs and rhs are associated with the same signal source and have the same last value.
true otherwise.
Template Parameters
TValueType that must provide bool operator==(T const&, T const&) noexcept.

◆ operator==() [1/2]

template<class T>
auto operator== ( SignalToken< T > const & lhs,
SignalToken< T > const & rhs ) -> bool
nodiscardconstexprnoexcept

Equality comparison.

Parameters
lhsLeft hand side of comparison.
rhsRIght hand side of comparison.
Returns
true if both lhs and rhs are associated with the same signal source and have the same last value.
false otherwise.
Template Parameters
TValueType that must provide bool operator==(T const&, T const&) noexcept.

◆ operator==() [2/2]

template<class T>
auto operator== ( SignalToken< T > const & lhs,
SignalToken< T > const & rhs ) -> bool
related

Equality comparison.

Parameters
lhsLeft hand side of comparison.
rhsRIght hand side of comparison.
Returns
true if both lhs and rhs are associated with the same signal source and have the same last value.
false otherwise.
Template Parameters
TValueType that must provide bool operator==(T const&, T const&) noexcept.

◆ Wait() [1/12]

template<class T>
auto Wait ( DifferenceTag ,
SignalToken< T > & token ) -> T
related

Wait until signal source changes and return difference (current - previous) value.

Note
Requires that T t2=t1-t0 is a valid expression where t0..t2 denotes an identifier of type T.
void Example(ion::SignalToken<int>& token) {
assert(token.IsValid());
int difference = Wait(ion::difference_tag, token);
}
constexpr auto IsValid() const noexcept -> bool
auto Wait(SignalToken< T > &token) noexcept -> T
Wait until signal source changes and return current value.
constexpr DifferenceTag difference_tag
Constant instance of DifferenceTag.
Definition signal.hpp:384
Precondition
token.IsValid() == true
Parameters
tokenSignal token.
Returns
Difference between current and previous signal value (current - previous).

◆ Wait() [2/12]

template<class T, class Predicate>
auto Wait ( DifferenceTag ,
SignalToken< T > & token,
Predicate && stop_waiting ) -> T
related

Wait until signal source changes and return difference (current - previous) value.

Note
Requires that T t2=t1-t0 is a valid expression where t0..t2 denotes an identifier of type T.
void Example(ion::SignalToken<int>& token) {
assert(token.IsValid());
int difference = Wait(ion::difference_tag, token);
}
Precondition
token.IsValid() == true
Parameters
tokenSignal token.
stop_waitingPredicate invoked with each new signal value and should return true when to stop waiting.
Returns
Difference between current and previous signal value (current - previous).
Template Parameters
PredicateCallable invokable with signature bool(T).

◆ Wait() [3/12]

template<class T>
auto Wait ( SignalToken< T > & token) -> T
related

Wait until signal source changes and return current value.

void Example(ion::SignalToken<int>& token) {
assert(token.IsValid());
int current = Wait(token);
}
Precondition
token.IsValid() == true
Parameters
tokenSignal token.
Returns
New signal source value.

◆ Wait() [4/12]

template<class T, class Predicate>
auto Wait ( SignalToken< T > & token,
Predicate && stop_waiting ) -> T
related

Wait with predicate.

Example using a predicate that waits until signal value is even.

void Example(ion::SignalToken<int>& token) {
assert(token.IsValid());
int current = Wait(token, [](int value) noexcept -> bool {
return value % 2;
});
}
Precondition
token.IsValid() == true
Parameters
tokenSignal token.
stop_waitingPredicate invoked with each new signal value and should return true when to stop waiting.
Returns
New signal source value.

◆ Wait() [5/12]

template<class T>
auto Wait ( StatusTag ,
SignalToken< T > & token ) -> Status< T >
related

Wait until signal source changes and return current and previous values.

void Example(ion::SignalToken<int>& token) {
assert(token.IsValid());
// or
auto [previous, current] = Wait(ion::status_tag, token);
}
constexpr StatusTag status_tag
Constant instance of StatusTag.
Definition signal.hpp:370
Represents signal source previous (old) and current (new) value.
Definition signal.hpp:329
Precondition
token.IsValid() == true
Parameters
tokenSignal token.
Returns
Status containing current and previous values.

◆ Wait() [6/12]

template<class T, class Predicate>
auto Wait ( StatusTag ,
SignalToken< T > & token,
Predicate && stop_waiting ) -> Status< T >
related

Wait with predicate.

Precondition
token.IsValid() == true
Parameters
tokenSignal token.
Returns
Status containing current and previous values.
Parameters
stop_waitingPredicate invoked with each new signal value and should return true when to stop waiting.
Template Parameters
PredicateCallable invokable with signature bool(T).
See also
Wait(StatusTag,SignalToken<T>&)

◆ Wait() [7/12]

template<class T>
auto Wait ( DifferenceTag ,
SignalToken< T > & token ) -> T
noexcept

Wait until signal source changes and return difference (current - previous) value.

Note
Requires that T t2=t1-t0 is a valid expression where t0..t2 denotes an identifier of type T.
void Example(ion::SignalToken<int>& token) {
assert(token.IsValid());
int difference = Wait(ion::difference_tag, token);
}
Precondition
token.IsValid() == true
Parameters
tokenSignal token.
Returns
Difference between current and previous signal value (current - previous).

◆ Wait() [8/12]

template<class T, class Predicate>
auto Wait ( DifferenceTag ,
SignalToken< T > & token,
Predicate && stop_waiting ) -> T
noexcept

Wait until signal source changes and return difference (current - previous) value.

Note
Requires that T t2=t1-t0 is a valid expression where t0..t2 denotes an identifier of type T.
void Example(ion::SignalToken<int>& token) {
assert(token.IsValid());
int difference = Wait(ion::difference_tag, token);
}
Precondition
token.IsValid() == true
Parameters
tokenSignal token.
stop_waitingPredicate invoked with each new signal value and should return true when to stop waiting.
Returns
Difference between current and previous signal value (current - previous).
Template Parameters
PredicateCallable invokable with signature bool(T).

◆ Wait() [9/12]

template<class T>
auto Wait ( SignalToken< T > & token) -> T
noexcept

Wait until signal source changes and return current value.

void Example(ion::SignalToken<int>& token) {
assert(token.IsValid());
int current = Wait(token);
}
Precondition
token.IsValid() == true
Parameters
tokenSignal token.
Returns
New signal source value.

◆ Wait() [10/12]

template<class T, class Predicate>
auto Wait ( SignalToken< T > & token,
Predicate && stop_waiting ) -> T
noexcept

Wait with predicate.

Example using a predicate that waits until signal value is even.

void Example(ion::SignalToken<int>& token) {
assert(token.IsValid());
int current = Wait(token, [](int value) noexcept -> bool {
return value % 2;
});
}
Precondition
token.IsValid() == true
Parameters
tokenSignal token.
stop_waitingPredicate invoked with each new signal value and should return true when to stop waiting.
Returns
New signal source value.

◆ Wait() [11/12]

template<class T>
auto Wait ( StatusTag ,
SignalToken< T > & token ) -> Status< T >
noexcept

Wait until signal source changes and return current and previous values.

void Example(ion::SignalToken<int>& token) {
assert(token.IsValid());
// or
auto [previous, current] = Wait(ion::status_tag, token);
}
Precondition
token.IsValid() == true
Parameters
tokenSignal token.
Returns
Status containing current and previous values.

◆ Wait() [12/12]

template<class T, class Predicate>
auto Wait ( StatusTag ,
SignalToken< T > & token,
Predicate && stop_waiting ) -> Status< T >
noexcept

Wait with predicate.

Precondition
token.IsValid() == true
Parameters
tokenSignal token.
Returns
Status containing current and previous values.
Parameters
stop_waitingPredicate invoked with each new signal value and should return true when to stop waiting.
Template Parameters
PredicateCallable invokable with signature bool(T).
See also
Wait(StatusTag,SignalToken<T>&)

◆ WaitAny() [1/6]

template<class T1, class T2>
auto WaitAny ( DifferenceTag ,
SignalToken< T1 > & token1,
SignalToken< T2 > & token2 ) -> WaitAnyResult< T1, T2 >
related

Wait for either of two signals to change.

Precondition
token1.IsValid() && token2.IsValid()
Parameters
token1First signal token.
token2Second signal token.
Returns
Wait result in which member index specify which of the two signals has a new value. Member result contains the difference as "current value" - "previous value" of the signals.

◆ WaitAny() [2/6]

template<class T1, class T2>
auto WaitAny ( SignalToken< T1 > & token1,
SignalToken< T2 > & token2 ) -> WaitAnyResult< T1, T2 >
related

Wait for either of two signals to change.

Precondition
token1.IsValid() && token2.IsValid()
Parameters
token1First signal token.
token2Second signal token.
Returns
Wait result in which member index specify which of the two signals has a new value. Member result contains the current value of the signals.

◆ WaitAny() [3/6]

template<class T1, class T2>
auto WaitAny ( StatusTag ,
SignalToken< T1 > & token1,
SignalToken< T2 > & token2 ) -> WaitAnyResult< Status< T1 >, Status< T2 > >
related

Wait for either of two signals to change.

Precondition
token1.IsValid() && token2.IsValid()
Parameters
token1First signal token.
token2Second signal token.
Returns
Wait result in which member index specify which of the two signals has a new value. Member result contains the current and previous value of the signals.

◆ WaitAny() [4/6]

template<class T1, class T2>
auto WaitAny ( DifferenceTag ,
SignalToken< T1 > & token1,
SignalToken< T2 > & token2 ) -> WaitAnyResult< T1, T2 >
noexcept

Wait for either of two signals to change.

Precondition
token1.IsValid() && token2.IsValid()
Parameters
token1First signal token.
token2Second signal token.
Returns
Wait result in which member index specify which of the two signals has a new value. Member result contains the difference as "current value" - "previous value" of the signals.

◆ WaitAny() [5/6]

template<class T1, class T2>
auto WaitAny ( SignalToken< T1 > & token1,
SignalToken< T2 > & token2 ) -> WaitAnyResult< T1, T2 >
noexcept

Wait for either of two signals to change.

Precondition
token1.IsValid() && token2.IsValid()
Parameters
token1First signal token.
token2Second signal token.
Returns
Wait result in which member index specify which of the two signals has a new value. Member result contains the current value of the signals.

◆ WaitAny() [6/6]

template<class T1, class T2>
auto WaitAny ( StatusTag ,
SignalToken< T1 > & token1,
SignalToken< T2 > & token2 ) -> WaitAnyResult< Status< T1 >, Status< T2 > >
noexcept

Wait for either of two signals to change.

Precondition
token1.IsValid() && token2.IsValid()
Parameters
token1First signal token.
token2Second signal token.
Returns
Wait result in which member index specify which of the two signals has a new value. Member result contains the current and previous value of the signals.