Commit f3a00610 authored by Andrii Grynenko's avatar Andrii Grynenko Committed by Facebook Github Bot

Simplify observable state

Summary: Merge two mutexes together and get rid of atomics.

Reviewed By: yfeldblum

Differential Revision: D14236244

fbshipit-source-id: 0b97d519e72322377e225a0cc8975e3a2a86ec31
parent 670768f1
...@@ -28,11 +28,11 @@ class ObserverCreatorContext { ...@@ -28,11 +28,11 @@ class ObserverCreatorContext {
template <typename... Args> template <typename... Args>
ObserverCreatorContext(Args&&... args) ObserverCreatorContext(Args&&... args)
: observable_(std::forward<Args>(args)...) { : observable_(std::forward<Args>(args)...) {
updateValue(); state_->updateValue(Traits::get(observable_));
} }
~ObserverCreatorContext() { ~ObserverCreatorContext() {
if (value_.copy()) { if (state_->value) {
Traits::unsubscribe(observable_); Traits::unsubscribe(observable_);
} }
} }
...@@ -42,8 +42,9 @@ class ObserverCreatorContext { ...@@ -42,8 +42,9 @@ class ObserverCreatorContext {
} }
std::shared_ptr<const T> get() { std::shared_ptr<const T> get() {
updateRequested_ = false; auto state = state_.lock();
return value_.copy(); state->updateRequested = false;
return state->value;
} }
void update() { void update() {
...@@ -53,14 +54,13 @@ class ObserverCreatorContext { ...@@ -53,14 +54,13 @@ class ObserverCreatorContext {
// Additionally it helps avoid races between two different subscription // Additionally it helps avoid races between two different subscription
// callbacks (getting new value from observable and storing it into value_ // callbacks (getting new value from observable and storing it into value_
// is not atomic). // is not atomic).
std::lock_guard<std::mutex> lg(updateMutex_); auto state = state_.lock();
if (!updateValue()) { if (!state->updateValue(Traits::get(observable_))) {
// Value didn't change, so we can skip the version update. // Value didn't change, so we can skip the version update.
return; return;
} }
bool expected = false; if (!std::exchange(state->updateRequested, true)) {
if (updateRequested_.compare_exchange_strong(expected, true)) {
observer_detail::ObserverManager::scheduleRefreshNewVersion(coreWeak_); observer_detail::ObserverManager::scheduleRefreshNewVersion(coreWeak_);
} }
} }
...@@ -71,24 +71,24 @@ class ObserverCreatorContext { ...@@ -71,24 +71,24 @@ class ObserverCreatorContext {
} }
private: private:
bool updateValue() { struct State {
auto newValue = Traits::get(observable_); bool updateValue(std::shared_ptr<const T> newValue) {
auto newValuePtr = newValue.get(); auto newValuePtr = newValue.get();
if (!newValue) { if (!newValue) {
throw std::logic_error("Observable returned nullptr."); throw std::logic_error("Observable returned nullptr.");
}
value.swap(newValue);
return newValuePtr != newValue.get();
} }
value_.swap(newValue);
return newValuePtr != newValue.get();
}
folly::Synchronized<std::shared_ptr<const T>> value_; std::shared_ptr<const T> value;
std::atomic<bool> updateRequested_{false}; bool updateRequested{false};
};
folly::Synchronized<State, std::mutex> state_;
observer_detail::Core::WeakPtr coreWeak_; observer_detail::Core::WeakPtr coreWeak_;
Observable observable_; Observable observable_;
std::mutex updateMutex_;
}; };
} // namespace detail } // namespace detail
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment