-
Notifications
You must be signed in to change notification settings - Fork 16
WIP: Create RecursiveMutableProperty
#41
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
to observers is outside the scope of the synchronisation lock.
RecursiveMutableProperty where the sending of updatesRecursiveMutableProperty
|
It turns out that this approach won't work either. The problem is actually not in So it would seem it's not possible to solve this without changing ReactiveSwift itself 😕 |
|
Would you like me to migrate the PR to ReactiveSwift itself? Or u can do it? c: |
|
Oh, it's probably more difficult than I thought 🤔 |
|
I want to understand the motivation for not allowing recursive |
|
Trying to understand it too, but still can't 🌚 |
|
Maybe the reason is that if an observer sends event recursively, than the rest of observers will get the next event before the previous? Pseudocode: |
|
OpenCombine.PassthroughSubject seems to be implemented in a similar manner https://github.com/OpenCombine/OpenCombine/blob/master/Sources/OpenCombine/PassthroughSubject.swift#L68 |
|
Recursive, synchronous properties do not have sensible behaviour. The general expectation is that property setters have immediate effect: let property = MutableProperty(0)
property.value = 1
expect(property.value) == 1and that ReactiveSwift guarantees that the latest value you are notified of is the same as property.producer.startWithValues { value in
expect(value) == property.value
someOtherWorkThatReads(property) // sees the same `value` as you do in this scope
}ReactiveSwift calls out to multiple observers as a synchronous "did set" side effect. So if we allow any of the observer to modify the property, it invalidates these guarantees for all the remaining observers to be notified. If we buffer the mutation with a queue-drain model (i.e. what makes reentrant signals work), then we will violate the developer expectation of how properties work, since what you set via the setter would no longer be visible through the getter immediately. |
|
Recursive or reentrant signals will be enabled by ReactiveCocoa/ReactiveSwift#797. |
|
For the purpose of unidirectional data flow, you can employ a queue-drain model built around An example implementation: https://github.com/ReactiveCocoa/Loop/blob/develop/Loop/Floodgate.swift |
@maximkrouk TCA uses Thanks for the input @andersio. Simply by changing the let property = MutableProperty(0)
var values: [Int] = []
property.producer.startWithValues { value in
values.append(value)
if value == 42 {
property.value = 0
}
}
property.value = 1
property.value = 2
property.value = 42
expect(values) == [0, 1, 2, 42, 0]It would seem that even with ReactiveCocoa/ReactiveSwift#797 the above would not work? I guess that means that
Ok, so that's a yes 👍
Yes, RAS-TCA has exactly the same issues 😄 |
Create
RecursiveMutablePropertywhere the sending of updates to observers is outside the scope of the synchronisation lock.This is an attempt to avoid having to use
DispatchQueue.main.asyncin order to avoid deadlocks when observers of state send actions to the store which recursively modify the state.