Template Class ObservedVariable

Class Documentation

template<typename T, std::uint8_t Observers = 1>
class ObservedVariable

Adds immediate observer callbacks to synchronized, versioned storage.

Every set() invokes observers on the calling thread, even when the value is unchanged. Waiters wake only for a changed value. Use CE::State::VersionedVariable directly when callback thread affinity is undesirable. Callbacks run in array order after releasing the storage mutex, with this set’s argument, not a later snapshot. Their const reference is borrowed for the call. Concurrent/reentrant sets can overlap callbacks; callbacks protect their own targets. A throw propagates after publication and skips later observers without rollback.

Template Parameters:
  • T – Value type satisfying VersionedVariable’s copy/assignment/equality requirements.

  • Observers – Fixed callback count, including zero; this object is noncopyable/nonmovable.

Public Types

using Callback = std::function<void(const T&)>

Immediate observer receiving a borrowed reference to this set’s argument.

Public Functions

inline explicit ObservedVariable(T value, std::array<Callback, Observers> observers)

Stores an initial value and fixed ordered observer list.

Parameters:
  • value – Initial owned value, moved into synchronized storage at revision zero.

  • observers – Owned callable array; empty entries are skipped and borrowed captures must remain alive. Construction invokes no observer. Observers may be zero; no dynamic registration is provided.

inline ObservedVariable &operator=(T value)

Publishes through set() and returns this observer wrapper.

Parameters:

value – New value; observers run even for an equal value.

Returns:

This object; observer exceptions propagate after publication.

inline void set(T value)

Publishes the candidate, then calls each nonempty observer in array order.

See also

State utilities

Parameters:

value – Owned argument; callbacks borrow this argument for their synchronous invocation. Callbacks run on the caller after the value lock is released, even for unchanged values. They can overlap/reenter with other setters and protect their own targets. A callback throw skips later observers without rolling back the published value. Storage comparison/assignment exceptions prevent callback execution.

inline T get() const

Declaration: [[nodiscard]]

Copies the current value under the underlying storage lock.

Returns:

Owned copy; it can reflect a later writer than a callback currently running. Copy exceptions propagate; no observer runs.

inline ::CE::State::VersionedSnapshot<T> snapshot() const

Declaration: [[nodiscard]]

Copies a consistent value/revision pair.

Returns:

Owned storage snapshot, with pointee ownership determined by T. No observer runs; copy failures propagate.

inline std::uint64_t revision() const

Declaration: [[nodiscard]]

Samples the storage change generation.

Returns:

Revision advanced only for a different successfully assigned value, not every callback round.

inline ::CE::State::VersionedSnapshot<T> wait_for_change(std::uint64_t since) const

Declaration: [[nodiscard]]

Waits for a different revision and returns its current snapshot.

Parameters:

since – Previously observed revision.

Returns:

Owned value/revision; intermediate updates can coalesce. The object must outlive waiters. No timeout/cancellation is provided; an unchanged set invokes callbacks but does not wake this wait.

inline void wait_until_change() const

Waits for a change after sampling the revision at this call.

Changes earlier than this call are not unread events and need not wake it. The object must remain alive and a later different value must be published; there is no timeout or cancellation. Use wait_for_change() with a saved revision when an intervening update must not be missed.