diff --git a/folly/observer/Observer-inl.h b/folly/observer/Observer-inl.h index 5b5aac06683..e4bfbdd072a 100644 --- a/folly/observer/Observer-inl.h +++ b/folly/observer/Observer-inl.h @@ -82,7 +82,7 @@ observer::Observer> makeValueObserver(F&& creator) { namespace observer { template -Snapshot Observer::getSnapshot() const { +Snapshot Observer::getSnapshot() const noexcept { auto data = core_->getData(); return Snapshot( *core_, diff --git a/folly/observer/Observer.h b/folly/observer/Observer.h index 83f78586dee..169dc365382 100644 --- a/folly/observer/Observer.h +++ b/folly/observer/Observer.h @@ -45,6 +45,9 @@ namespace observer { * Snapshot will hold a view of the object, even if object in the Observer * gets updated. * + * Note: fetching a snapshot from Observer will never block/fail. And returned + * snapshow will never contain a nullptr. + * * * What makes Observer powerful is its ability to track updates to other * Observers. Imagine we have two separate Observers A and B which hold @@ -168,12 +171,24 @@ class Snapshot { public: const T& operator*() const { return *get(); } + /** + * Never returns nullptr + */ const T* operator->() const { return get(); } + /** + * Never returns nullptr + */ const T* get() const { return data_.get(); } + /** + * Never returns nullptr + */ std::shared_ptr getShared() const& { return data_; } + /** + * Never returns nullptr + */ std::shared_ptr getShared() && { return std::move(data_); } /** @@ -225,8 +240,12 @@ class Observer { public: explicit Observer(observer_detail::Core::Ptr core); - Snapshot getSnapshot() const; - Snapshot operator*() const { return getSnapshot(); } + /** + * Never throws or blocks + * Never returns an empty snapshot + */ + Snapshot getSnapshot() const noexcept; + Snapshot operator*() const noexcept { return getSnapshot(); } /** * Check if we have a newer version of the observed object than the snapshot.