/* * Copyright 2016-present Facebook, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #pragma once #include #include #include #include #include #include #include #include #include namespace folly { namespace observer_detail { class ObserverManager; /** * Core stores the current version of the object held by Observer. It also keeps * all dependencies and dependents of the Observer. */ class Core : public std::enable_shared_from_this { public: using Ptr = std::shared_ptr; using WeakPtr = std::weak_ptr; /** * Blocks until creator is successfully run by ObserverManager */ static Ptr create(folly::Function()> creator); /** * View of the observed object and its version */ struct VersionedData { VersionedData() {} VersionedData(std::shared_ptr data_, size_t version_) : data(std::move(data_)), version(version_) {} std::shared_ptr data; size_t version{0}; }; /** * Gets current view of the observed object. * This is safe to call from any thread. If this is called from other Observer * functor then that Observer is marked as dependent on current Observer. */ VersionedData getData(); /** * Gets the version of the observed object. */ size_t getVersion() const { return version_; } /** * Get the last version at which the observed object was actually changed. */ size_t getVersionLastChange() { return versionLastChange_; } /** * Check if the observed object needs to be re-computed. Returns the version * of last change. If force is true, re-computes the observed object, even if * dependencies didn't change. * * This should be only called from ObserverManager thread. */ size_t refresh(size_t version, bool force = false); ~Core(); private: explicit Core(folly::Function()> creator); void addDependent(Core::WeakPtr dependent); void removeStaleDependents(); using Dependents = std::vector; using Dependencies = std::unordered_set; folly::Synchronized dependents_; folly::Synchronized dependencies_; std::atomic version_{0}; std::atomic versionLastChange_{0}; folly::Synchronized data_; folly::Function()> creator_; std::mutex refreshMutex_; }; } // namespace observer_detail } // namespace folly