proxygen
folly::observer_detail::Core Class Reference

#include <Core.h>

Inheritance diagram for folly::observer_detail::Core:

Classes

struct  VersionedData
 

Public Types

using Ptr = std::shared_ptr< Core >
 
using WeakPtr = std::weak_ptr< Core >
 

Public Member Functions

VersionedData getData ()
 
size_t getVersion () const
 
size_t getVersionLastChange ()
 
size_t refresh (size_t version, bool force=false)
 
 ~Core ()
 

Static Public Member Functions

static Ptr create (folly::Function< std::shared_ptr< const void >()> creator)
 

Private Types

using Dependents = std::vector< WeakPtr >
 
using Dependencies = std::unordered_set< Ptr >
 

Private Member Functions

 Core (folly::Function< std::shared_ptr< const void >()> creator)
 
void addDependent (Core::WeakPtr dependent)
 
void removeStaleDependents ()
 

Private Attributes

folly::Synchronized< Dependentsdependents_
 
folly::Synchronized< Dependenciesdependencies_
 
std::atomic< size_t > version_ {0}
 
std::atomic< size_t > versionLastChange_ {0}
 
folly::Synchronized< VersionedDatadata_
 
folly::Function< std::shared_ptr< const void >)> creator_
 
std::mutex refreshMutex_
 

Detailed Description

Core stores the current version of the object held by Observer. It also keeps all dependencies and dependents of the Observer.

Definition at line 38 of file Core.h.

Member Typedef Documentation

using folly::observer_detail::Core::Dependencies = std::unordered_set<Ptr>
private

Definition at line 100 of file Core.h.

using folly::observer_detail::Core::Dependents = std::vector<WeakPtr>
private

Definition at line 99 of file Core.h.

using folly::observer_detail::Core::Ptr = std::shared_ptr<Core>

Definition at line 40 of file Core.h.

Definition at line 41 of file Core.h.

Constructor & Destructor Documentation

folly::observer_detail::Core::~Core ( )

Definition at line 150 of file Core.cpp.

References dependencies_.

Referenced by getVersionLastChange().

150  {
151  dependencies_.withWLock([](const Dependencies& dependencies) {
152  for (const auto& dependecy : dependencies) {
153  dependecy->removeStaleDependents();
154  }
155  });
156 }
folly::Synchronized< Dependencies > dependencies_
Definition: Core.h:103
std::unordered_set< Ptr > Dependencies
Definition: Core.h:100
folly::observer_detail::Core::Core ( folly::Function< std::shared_ptr< const void >()>  creator)
explicitprivate

Definition at line 147 of file Core.cpp.

Referenced by create(), and getVersionLastChange().

148  : creator_(std::move(creator)) {}
constexpr detail::Map< Move > move
Definition: Base-inl.h:2567
folly::Function< std::shared_ptr< const void >)> creator_
Definition: Core.h:110

Member Function Documentation

void folly::observer_detail::Core::addDependent ( Core::WeakPtr  dependent)
private

Definition at line 163 of file Core.cpp.

References dependents_, and folly::gen::move.

Referenced by getVersionLastChange().

163  {
164  dependents_.withWLock([&](Dependents& dependents) {
165  dependents.push_back(std::move(dependent));
166  });
167 }
constexpr detail::Map< Move > move
Definition: Base-inl.h:2567
folly::Synchronized< Dependents > dependents_
Definition: Core.h:102
std::vector< WeakPtr > Dependents
Definition: Core.h:99
Core::Ptr folly::observer_detail::Core::create ( folly::Function< std::shared_ptr< const void >()>  creator)
static

Blocks until creator is successfully run by ObserverManager

Definition at line 158 of file Core.cpp.

References Core(), and folly::gen::move.

Referenced by folly::observer::makeObserver().

158  {
159  auto core = Core::Ptr(new Core(std::move(creator)));
160  return core;
161 }
Core(folly::Function< std::shared_ptr< const void >()> creator)
Definition: Core.cpp:147
constexpr detail::Map< Move > move
Definition: Base-inl.h:2567
std::shared_ptr< Core > Ptr
Definition: Core.h:40
Core::VersionedData folly::observer_detail::Core::getData ( )

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.

Definition at line 25 of file Core.cpp.

References data_, folly::observer_detail::ObserverManager::getVersion(), folly::observer_detail::ObserverManager::inManagerThread(), folly::observer_detail::ObserverManager::DependencyRecorder::markDependency(), refresh(), version, and version_.

25  {
27  return data_.copy();
28  }
29 
31 
33 
34  if (version_ >= version) {
35  return data_.copy();
36  }
37 
39 
40  DCHECK_GE(version_, version);
41  return data_.copy();
42 }
ProtocolVersion version
size_t refresh(size_t version, bool force=false)
Definition: Core.cpp:44
folly::Synchronized< VersionedData > data_
Definition: Core.h:108
std::atomic< size_t > version_
Definition: Core.h:105
size_t folly::observer_detail::Core::getVersion ( ) const
inline

Gets the version of the observed object.

Definition at line 71 of file Core.h.

References version_.

71  {
72  return version_;
73  }
std::atomic< size_t > version_
Definition: Core.h:105
size_t folly::observer_detail::Core::getVersionLastChange ( )
inline

Get the last version at which the observed object was actually changed.

Definition at line 78 of file Core.h.

References addDependent(), Core(), refresh(), removeStaleDependents(), folly::observer_detail::Core::VersionedData::version, versionLastChange_, and ~Core().

Referenced by folly::observer::Observer< T >::needRefresh().

78  {
79  return versionLastChange_;
80  }
std::atomic< size_t > versionLastChange_
Definition: Core.h:106
size_t folly::observer_detail::Core::refresh ( size_t  version,
bool  force = false 
)

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.

Definition at line 44 of file Core.cpp.

References folly::Synchronized< T, Mutex >::copy(), creator_, data_, dependencies_, dependents_, folly::exceptionStr(), folly::observer_detail::ObserverManager::inManagerThread(), folly::observer_detail::ObserverManager::DependencyRecorder::markRefreshDependency(), folly::gen::move, refreshMutex_, folly::observer_detail::ObserverManager::DependencyRecorder::release(), folly::observer_detail::ObserverManager::scheduleRefresh(), SCOPE_EXIT, folly::observer_detail::ObserverManager::DependencyRecorder::unmarkRefreshDependency(), version, version_, and versionLastChange_.

Referenced by getData(), and getVersionLastChange().

44  {
46 
48  SCOPE_EXIT {
50  };
51 
52  if (version_ >= version) {
53  return versionLastChange_;
54  }
55 
56  {
57  std::lock_guard<std::mutex> lgRefresh(refreshMutex_);
58 
59  // Recheck in case this code was already refreshed
60  if (version_ >= version) {
61  return versionLastChange_;
62  }
63 
64  bool needRefresh = force || version_ == 0;
65 
66  ObserverManager::DependencyRecorder dependencyRecorder(*this);
67 
68  // This can be run in parallel, but we expect most updates to propagate
69  // bottom to top.
70  dependencies_.withRLock([&](const Dependencies& dependencies) {
71  for (const auto& dependency : dependencies) {
72  try {
73  if (dependency->refresh(version) > version_) {
74  needRefresh = true;
75  break;
76  }
77  } catch (...) {
78  LOG(ERROR) << "Exception while checking dependencies for updates: "
79  << exceptionStr(std::current_exception());
80 
81  needRefresh = true;
82  break;
83  }
84  }
85  });
86 
87  if (!needRefresh) {
88  version_ = version;
89  return versionLastChange_;
90  }
91 
92  try {
93  {
94  VersionedData newData{creator_(), version};
95  if (!newData.data) {
96  throw std::logic_error("Observer creator returned nullptr.");
97  }
98  data_.swap(newData);
99  }
100 
102  } catch (...) {
103  LOG(ERROR) << "Exception while refreshing Observer: "
104  << exceptionStr(std::current_exception());
105 
106  if (version_ == 0) {
107  // Re-throw exception if this is the first time we run creator
108  throw;
109  }
110  }
111 
112  version_ = version;
113 
114  if (versionLastChange_ != version) {
115  return versionLastChange_;
116  }
117 
118  auto newDependencies = dependencyRecorder.release();
119  dependencies_.withWLock([&](Dependencies& dependencies) {
120  for (const auto& dependency : newDependencies) {
121  if (!dependencies.count(dependency)) {
122  dependency->addDependent(this->shared_from_this());
123  }
124  }
125 
126  for (const auto& dependency : dependencies) {
127  if (!newDependencies.count(dependency)) {
128  dependency->removeStaleDependents();
129  }
130  }
131 
132  dependencies = std::move(newDependencies);
133  });
134  }
135 
136  auto dependents = dependents_.copy();
137 
138  for (const auto& dependentWeak : dependents) {
139  if (auto dependent = dependentWeak.lock()) {
141  }
142  }
143 
144  return versionLastChange_;
145 }
std::mutex refreshMutex_
Definition: Core.h:112
fbstring exceptionStr(const std::exception &e)
constexpr detail::Map< Move > move
Definition: Base-inl.h:2567
std::atomic< size_t > versionLastChange_
Definition: Core.h:106
#define SCOPE_EXIT
Definition: ScopeGuard.h:274
folly::Synchronized< Dependents > dependents_
Definition: Core.h:102
ProtocolVersion version
folly::Synchronized< Dependencies > dependencies_
Definition: Core.h:103
std::unordered_set< Ptr > Dependencies
Definition: Core.h:100
folly::Function< std::shared_ptr< const void >)> creator_
Definition: Core.h:110
folly::Synchronized< VersionedData > data_
Definition: Core.h:108
static void scheduleRefresh(Core::Ptr core, size_t minVersion, bool force=false)
std::atomic< size_t > version_
Definition: Core.h:105
void copy(T *target) const
Definition: Synchronized.h:721
void folly::observer_detail::Core::removeStaleDependents ( )
private

Definition at line 169 of file Core.cpp.

References dependents_, i, and folly::f14::swap().

Referenced by getVersionLastChange().

169  {
170  // This is inefficient, the assumption is that we won't have many dependents
171  dependents_.withWLock([](Dependents& dependents) {
172  for (size_t i = 0; i < dependents.size(); ++i) {
173  if (dependents[i].expired()) {
174  std::swap(dependents[i], dependents.back());
175  dependents.pop_back();
176  --i;
177  }
178  }
179  });
180 }
folly::Synchronized< Dependents > dependents_
Definition: Core.h:102
std::vector< WeakPtr > Dependents
Definition: Core.h:99
void swap(SwapTrackingAlloc< T > &, SwapTrackingAlloc< T > &)
Definition: F14TestUtil.h:414

Member Data Documentation

folly::Function<std::shared_ptr<const void>)> folly::observer_detail::Core::creator_
private

Definition at line 110 of file Core.h.

Referenced by refresh().

folly::Synchronized<VersionedData> folly::observer_detail::Core::data_
private

Definition at line 108 of file Core.h.

Referenced by getData(), and refresh().

folly::Synchronized<Dependencies> folly::observer_detail::Core::dependencies_
private

Definition at line 103 of file Core.h.

Referenced by refresh(), and ~Core().

folly::Synchronized<Dependents> folly::observer_detail::Core::dependents_
private

Definition at line 102 of file Core.h.

Referenced by addDependent(), refresh(), and removeStaleDependents().

std::mutex folly::observer_detail::Core::refreshMutex_
private

Definition at line 112 of file Core.h.

Referenced by refresh().

std::atomic<size_t> folly::observer_detail::Core::version_ {0}
private

Definition at line 105 of file Core.h.

Referenced by getData(), getVersion(), and refresh().

std::atomic<size_t> folly::observer_detail::Core::versionLastChange_ {0}
private

Definition at line 106 of file Core.h.

Referenced by getVersionLastChange(), and refresh().


The documentation for this class was generated from the following files: