map_each previously was written such that if a chain of mappings fed
each other, a deadlock could occur because while the first one was
mapped, the second callback gets invoked and tries to update the first
value while it's still being held.
This refactor switches from std Mutex to parking_lot, allowing me to
remove a workaround for needing to run drop callbacks in a separate
thread during the drop of a DynamicGuard.
In addition to that change, the lower level `map_generational` calls now
take a DynamicGuard as their parameter. This allows these functions to
drop ownership of the referenced data during the callback.
The map_each implementation takes advantage of this by ensuring that the
guard is dropped before set is invoked, minimizing potential lock overlaps.
With this refactor, some old code of mine with complex validations now works
again.
Closes#98
This finishes my initial refactoring of the dynamic system to add
support for several dataflows including:
- Pure data sources that can be implemented using an `Owned<T>` at the
root of a graph of `Dynamic<U>`/`DynamicReader<U>`s.
- Read-only data sinks. I thought this would be more useful across other
widgets, but in general, Progress and Label seem like the only types
that this applies to currently.
- The ability to mix/match Dynamic/DynamicReader in tuple-based
for_each/map_each.
After trying to run Gooey again on my Mac for the first time in a few
weeks, I found that I ran into the Condvar issue again. Rather than
pasting AssertUnwindSafe in those files, I've both reported the
discrepency in unwind safety (rust-lang/rust#118009) and moved the
workaround into a type that only uses AssertUnwindsafe when compiling
for Apple.
measure() now is layout(). LayoutContext can either persist layout
information or be used temporarily for measurement. While this caching
is constantly thrown out currently, this is a step towards being able to
only re-layout widgets if they've been invalidated.