Consistently have the namespace closing comment
[folly.git] / folly / experimental / observer / detail / Core.cpp
index c4e317ec65eaaafb5693c706ed339d76165e728c..c692c04a55ca51414ea6e1649e4bc1466369cfd0 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2016 Facebook, Inc.
+ * Copyright 2017 Facebook, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
 #include <folly/experimental/observer/detail/Core.h>
+
+#include <folly/ExceptionString.h>
 #include <folly/experimental/observer/detail/ObserverManager.h>
 
 namespace folly {
@@ -41,12 +44,15 @@ Core::VersionedData Core::getData() {
 size_t Core::refresh(size_t version, bool force) {
   CHECK(ObserverManager::inManagerThread());
 
+  ObserverManager::DependencyRecorder::markRefreshDependency(*this);
+  SCOPE_EXIT {
+    ObserverManager::DependencyRecorder::unmarkRefreshDependency(*this);
+  };
+
   if (version_ >= version) {
     return versionLastChange_;
   }
 
-  bool refreshDependents = false;
-
   {
     std::lock_guard<std::mutex> lgRefresh(refreshMutex_);
 
@@ -57,11 +63,21 @@ size_t Core::refresh(size_t version, bool force) {
 
     bool needRefresh = force || version_ == 0;
 
+    ObserverManager::DependencyRecorder dependencyRecorder(*this);
+
     // This can be run in parallel, but we expect most updates to propagate
     // bottom to top.
     dependencies_.withRLock([&](const Dependencies& dependencies) {
       for (const auto& dependency : dependencies) {
-        if (dependency->refresh(version) > version_) {
+        try {
+          if (dependency->refresh(version) > version_) {
+            needRefresh = true;
+            break;
+          }
+        } catch (...) {
+          LOG(ERROR) << "Exception while checking dependencies for updates: "
+                     << exceptionStr(std::current_exception());
+
           needRefresh = true;
           break;
         }
@@ -73,8 +89,6 @@ size_t Core::refresh(size_t version, bool force) {
       return versionLastChange_;
     }
 
-    ObserverManager::DependencyRecorder dependencyRecorder;
-
     try {
       {
         VersionedData newData{creator_(), version};
@@ -85,7 +99,6 @@ size_t Core::refresh(size_t version, bool force) {
       }
 
       versionLastChange_ = version;
-      refreshDependents = true;
     } catch (...) {
       LOG(ERROR) << "Exception while refreshing Observer: "
                  << exceptionStr(std::current_exception());
@@ -98,6 +111,10 @@ size_t Core::refresh(size_t version, bool force) {
 
     version_ = version;
 
+    if (versionLastChange_ != version) {
+      return versionLastChange_;
+    }
+
     auto newDependencies = dependencyRecorder.release();
     dependencies_.withWLock([&](Dependencies& dependencies) {
       for (const auto& dependency : newDependencies) {
@@ -116,13 +133,11 @@ size_t Core::refresh(size_t version, bool force) {
     });
   }
 
-  if (refreshDependents) {
-    auto dependents = dependents_.copy();
+  auto dependents = dependents_.copy();
 
-    for (const auto& dependentWeak : dependents) {
-      if (auto dependent = dependentWeak.lock()) {
-        ObserverManager::scheduleRefresh(std::move(dependent), version);
-      }
+  for (const auto& dependentWeak : dependents) {
+    if (auto dependent = dependentWeak.lock()) {
+      ObserverManager::scheduleRefresh(std::move(dependent), version);
     }
   }
 
@@ -163,5 +178,5 @@ void Core::removeStaleDependents() {
     }
   });
 }
-}
-}
+} // namespace observer_detail
+} // namespace folly