Skip to content

ui::PropertyBase

Header: winui/core/Property.hpp.

The non-template core of Property and Signal: the head of the intrusive observer list and the dispatch loop. Non-copyable; never used on its own and never owned through a pointer to it (the destructor is protected and non-virtual). Its one public member is observer_count().

Example:

ui::Property<bool> busy{false};
ui::Subscription log = busy.observe([](const bool& on) { std::printf("busy: %d\n", on); });

// A debug overlay can show how many handlers a piece of state still drives.
std::printf("busy has %zu observers\n", busy.observer_count()); // 1
log.reset();
std::printf("busy has %zu observers\n", busy.observer_count()); // 0

PropertyBase

PropertyBase(const PropertyBase&) = delete

Not copyable: subscriptions point at this object.

operator=

PropertyBase& operator=(const PropertyBase&) = delete

Not copyable: subscriptions point at this object.

observer_count

std::size_t observer_count() const noexcept

How many live subscriptions currently observe this property. Exposed for debugging tools; nothing in the framework branches on it.

PropertyBase

PropertyBase() = default

~PropertyBase

~PropertyBase()

Non-virtual and protected: a Property is never owned or destroyed through a PropertyBase*, so the type needs no vtable.

attach

Subscription attach(Callback<void(const void*)> fn, std::source_location where = std::source_location::current()) const

Const because subscribing is not a write: it links an edge into the observer list and changes nothing a reader of the value can see. That is what lets a property whose one writer is someone else (Window::state(), written only by the window host) be handed out as const Property<T>& and still be bound to.

where names the observe() that called it, for the thread check.

dispatch

void dispatch(const void* value)

Invoke every observer, newest subscription first. A handler may reset, destroy or move any Subscription of this source, its own and the next one in line included, and may destroy the source itself: the observers that are left are still reached, and nobody is called after the source is gone. A subscription made during the dispatch is first told of the next change. A handler that resets its own Subscription destroys its own captures by doing so, and must not touch them afterwards.

check_write

void check_write(std::string_view call, const std::source_location& where) const

The thread check for a write about to be dispatched: the first write that reaches an observer claims the calling thread, and a later one from any other thread is reported. A source nobody observes is not checked. call names it ("ui::Property::set"); empty takes the name from where.