CatapultServer  v0.5.0.1 (Elephant)
SynchronizedCache.h
Go to the documentation of this file.
1 
21 #pragma once
24 #include <boost/optional.hpp>
25 
26 namespace catapult { namespace cache {
27 
28  namespace detail {
29  // region CacheViewReadLockPair
30 
33  template<typename TCacheView>
35  public:
38  : CacheView(std::move(cacheView))
39  , ReadLock(std::move(readLock))
40  {}
41 
42  public:
44  TCacheView CacheView;
45 
48  };
49 
50  // endregion
51 
52  // region CacheViewAccessor
53 
55  template<typename TCacheView>
57  public:
59  explicit CacheViewAccessor(TCacheView* pCacheView) : m_pCacheView(pCacheView)
60  {}
61 
62  public:
64  explicit operator bool() const {
65  return !!m_pCacheView;
66  }
67 
69  const TCacheView* operator->() const {
70  return m_pCacheView;
71  }
72 
74  const TCacheView& operator*() const {
75  return *m_pCacheView;
76  }
77 
78  public:
80  TCacheView* operator->() {
81  return m_pCacheView;
82  }
83 
85  TCacheView& operator*() {
86  return *m_pCacheView;
87  }
88 
89  private:
90  TCacheView* m_pCacheView;
91  };
92 
93  // endregion
94  }
95 
96  // region LockedCacheView
97 
100  template<typename TCacheView>
101  class LockedCacheView : public detail::CacheViewAccessor<TCacheView> {
102  public:
105  : detail::CacheViewAccessor<TCacheView>(&m_cacheView)
106  , m_cacheView(std::move(cacheView))
107  , m_readLock(std::move(readLock))
108  {}
109 
113  : detail::CacheViewAccessor<TCacheView>(&m_cacheView)
114  , m_cacheView(std::move(rhs.m_cacheView))
115  , m_readLock(std::move(rhs.m_readLock))
116  {}
117 
118  private:
119  TCacheView m_cacheView;
121  };
122 
123  // endregion
124 
125  // region LockedCacheDelta
126 
128  template<typename TCacheView>
129  class LockedCacheDelta : public detail::CacheViewAccessor<TCacheView> {
130  public:
132  explicit LockedCacheDelta(const std::shared_ptr<detail::CacheViewReadLockPair<TCacheView>>& pPair)
133  : detail::CacheViewAccessor<TCacheView>(&pPair->CacheView)
134  , m_pPair(pPair)
135  {}
136 
137  private:
138  std::shared_ptr<detail::CacheViewReadLockPair<TCacheView>> m_pPair;
139  };
140 
141  // endregion
142 
143  // region OptionalLockedCacheDelta
144 
146  template<typename TCacheView>
148  public:
150  OptionalLockedCacheDelta() : detail::CacheViewAccessor<TCacheView>(nullptr)
151  {}
152 
155  : detail::CacheViewAccessor<TCacheView>(&cacheView)
156  , m_readLock(std::move(readLock))
157  {}
158 
159  private:
160  boost::optional<utils::SpinReaderWriterLock::ReaderLockGuard> m_readLock;
161  };
162 
163  // endregion
164 
165  // region LockableCacheDelta
166 
167  template<typename TCacheDelta>
169  public:
172  LockableCacheDelta(TCacheDelta&& cacheDelta, const size_t& commitCounter, utils::SpinReaderWriterLock& lock)
173  : m_cacheDelta(std::move(cacheDelta))
174  , m_initialCommitCount(commitCounter)
175  , m_commitCounter(commitCounter)
176  , m_lock(lock)
177  {}
178 
179  public:
183  auto readLock = m_lock.acquireReader();
186  : OptionalLockedCacheDelta<TCacheDelta>(m_cacheDelta, std::move(readLock));
187  }
188 
189  private:
190  TCacheDelta m_cacheDelta;
192  const size_t& m_commitCounter;
194  };
195 
196  // endregion
197 
198  // region SynchronizedCache
199 
201  template<typename TCache>
203  public:
204  using CacheValueType = typename TCache::CacheValueType;
205  using CacheViewType = typename TCache::CacheViewType;
206  using CacheDeltaType = typename TCache::CacheDeltaType;
208 
209  public:
211  explicit SynchronizedCache(TCache&& cache)
212  : m_cache(std::move(cache))
213  , m_commitCounter(0)
214  {}
215 
216  public:
219  auto readLock = m_lock.acquireReader();
220  return LockedCacheView<CacheViewType>(m_cache.createView(), std::move(readLock));
221  }
222 
226  auto readLock = m_lock.acquireReader();
227 
228  // notice that this is not a foolproof check since multiple threads could create multiple deltas at the same time
229  // but it is good enough as a sanity check
230  if (m_pWeakDeltaPair.lock())
231  CATAPULT_THROW_RUNTIME_ERROR("only a single attached delta of a cache is allowed at a time");
232 
233  auto delta = m_cache.createDelta();
234  auto pPair = std::make_shared<detail::CacheViewReadLockPair<CacheDeltaType>>(std::move(delta), std::move(readLock));
235  m_pWeakDeltaPair = pPair;
236  return LockedCacheDelta<CacheDeltaType>(pPair);
237  }
238 
242  auto readLock = m_lock.acquireReader();
243  auto delta = m_cache.createDetachedDelta();
244  return LockableCacheDelta<CacheDeltaType>(std::move(delta), m_commitCounter, m_lock);
245  }
246 
248  void commit() {
249  auto pDeltaPair = m_pWeakDeltaPair.lock();
250  if (!pDeltaPair)
251  CATAPULT_THROW_RUNTIME_ERROR("attempting to commit changes to a cache without any outstanding attached deltas");
252 
253  auto writeLock = pDeltaPair->ReadLock.promoteToWriter();
254  m_cache.commit(pDeltaPair->CacheView);
255  ++m_commitCounter;
256  }
257 
258  protected:
260  TCache& cache() {
261  return m_cache;
262  }
263 
264  private:
265  TCache m_cache;
267  std::weak_ptr<detail::CacheViewReadLockPair<CacheDeltaType>> m_pWeakDeltaPair;
269  };
270 
271  // endregion
272 
273  // region SynchronizedCacheWithInit
274 
276  template<typename TCache>
278  public:
280  explicit SynchronizedCacheWithInit(TCache&& cache)
281  : SynchronizedCache<TCache>(std::move(cache))
282  , m_isInitCalled(false)
283  {}
284 
285  public:
287  template<typename... TArgs>
288  void init(TArgs&&... args) {
289  if (m_isInitCalled)
290  CATAPULT_THROW_RUNTIME_ERROR("init has already been called for cache");
291 
292  this->cache().init(std::forward<TArgs>(args)...);
293  m_isInitCalled = true;
294  }
295 
296  private:
298  };
299 
300  // endregion
301 }}
catapult::cache::detail::CacheViewReadLockPair::ReadLock
utils::SpinReaderWriterLock::ReaderLockGuard ReadLock
Read lock.
Definition: SynchronizedCache.h:47
catapult::cache::LockedCacheView
Definition: SynchronizedCache.h:101
catapult::cache::SynchronizedCacheWithInit
Decorator that synchronizes access to a cache and allows custom cache initialization.
Definition: SynchronizedCache.h:277
catapult::cache::detail::CacheViewAccessor
A cache view accessor.
Definition: SynchronizedCache.h:56
catapult::cache::SynchronizedCache::SynchronizedCache
SynchronizedCache(TCache &&cache)
Creates a synchronized decorator around cache.
Definition: SynchronizedCache.h:211
catapult::cache::LockableCacheDelta::m_commitCounter
const size_t & m_commitCounter
Definition: SynchronizedCache.h:192
catapult::cache::detail::CacheViewReadLockPair::CacheView
TCacheView CacheView
Cache view.
Definition: SynchronizedCache.h:44
catapult::cache::SynchronizedCache::commit
void commit()
Commits all pending changes to the underlying storage.
Definition: SynchronizedCache.h:248
catapult::cache::SynchronizedCache< BasicAccountStateCache >::CacheReadOnlyType
typename BasicAccountStateCache ::CacheReadOnlyType CacheReadOnlyType
Definition: SynchronizedCache.h:207
catapult::cache::SynchronizedCacheWithInit::m_isInitCalled
bool m_isInitCalled
Definition: SynchronizedCache.h:297
catapult::cache::SynchronizedCache::m_cache
TCache m_cache
Definition: SynchronizedCache.h:265
catapult::cache::SynchronizedCache< BasicAccountStateCache >::CacheDeltaType
typename BasicAccountStateCache ::CacheDeltaType CacheDeltaType
Definition: SynchronizedCache.h:206
catapult::cache::SynchronizedCache::createView
LockedCacheView< CacheViewType > createView() const
Returns a locked cache view based on this cache.
Definition: SynchronizedCache.h:218
catapult::cache::LockableCacheDelta::m_initialCommitCount
size_t m_initialCommitCount
Definition: SynchronizedCache.h:191
catapult::cache::OptionalLockedCacheDelta::m_readLock
boost::optional< utils::SpinReaderWriterLock::ReaderLockGuard > m_readLock
Definition: SynchronizedCache.h:160
catapult::cache::LockedCacheView::LockedCacheView
LockedCacheView(TCacheView &&cacheView, utils::SpinReaderWriterLock::ReaderLockGuard &&readLock)
Creates a view around cacheView and readLock.
Definition: SynchronizedCache.h:104
catapult::cache::detail::CacheViewAccessor::operator*
TCacheView & operator*()
Gets a reference to the underlying cache view.
Definition: SynchronizedCache.h:85
catapult::cache::LockedCacheView::LockedCacheView
LockedCacheView(LockedCacheView &&rhs)
Definition: SynchronizedCache.h:112
catapult::cache::SynchronizedCache::m_lock
utils::SpinReaderWriterLock m_lock
Definition: SynchronizedCache.h:268
catapult::cache::LockableCacheDelta::LockableCacheDelta
LockableCacheDelta(TCacheDelta &&cacheDelta, const size_t &commitCounter, utils::SpinReaderWriterLock &lock)
Definition: SynchronizedCache.h:172
catapult::cache::detail::CacheViewAccessor::operator->
const TCacheView * operator->() const
Gets a const pointer to the underlying cache view.
Definition: SynchronizedCache.h:69
SpinReaderWriterLock.h
catapult::cache::detail::CacheViewAccessor::m_pCacheView
TCacheView * m_pCacheView
Definition: SynchronizedCache.h:90
catapult::utils::BasicSpinReaderWriterLock::acquireReader
ReaderLockGuard acquireReader()
Blocks until a reader lock can be acquired.
Definition: SpinReaderWriterLock.h:153
catapult::cache::LockableCacheDelta::tryLock
OptionalLockedCacheDelta< TCacheDelta > tryLock()
Definition: SynchronizedCache.h:182
catapult::cache::OptionalLockedCacheDelta::OptionalLockedCacheDelta
OptionalLockedCacheDelta(TCacheView &cacheView, utils::SpinReaderWriterLock::ReaderLockGuard &&readLock)
Creates a view around cacheView and pReadLock.
Definition: SynchronizedCache.h:154
catapult::cache::LockedCacheView::m_readLock
utils::SpinReaderWriterLock::ReaderLockGuard m_readLock
Definition: SynchronizedCache.h:120
catapult::cache::LockedCacheDelta
A cache-delta, read-lock pair.
Definition: SynchronizedCache.h:129
catapult::cache::SynchronizedCache< BasicAccountStateCache >::CacheViewType
typename BasicAccountStateCache ::CacheViewType CacheViewType
Definition: SynchronizedCache.h:205
catapult::cache::OptionalLockedCacheDelta::OptionalLockedCacheDelta
OptionalLockedCacheDelta()
Creates a empty view.
Definition: SynchronizedCache.h:150
catapult::cache::LockableCacheDelta::m_lock
utils::SpinReaderWriterLock & m_lock
Definition: SynchronizedCache.h:193
catapult::validators::CacheReadOnlyType
typename cache::AccountRestrictionCacheTypes::CacheReadOnlyType CacheReadOnlyType
Definition: AddressInteractionValidator.cpp:30
catapult::cache::SynchronizedCache::cache
TCache & cache()
Gets a typed reference to the underlying cache.
Definition: SynchronizedCache.h:260
catapult::cache::SynchronizedCache
Decorator that synchronizes access to a cache.
Definition: SynchronizedCache.h:202
catapult::cache::LockedCacheDelta::LockedCacheDelta
LockedCacheDelta(const std::shared_ptr< detail::CacheViewReadLockPair< TCacheView >> &pPair)
Creates a view around pPair.
Definition: SynchronizedCache.h:132
catapult::cache::LockableCacheDelta::m_cacheDelta
TCacheDelta m_cacheDelta
Definition: SynchronizedCache.h:190
catapult::cache::SynchronizedCache< BasicAccountStateCache >::CacheValueType
typename BasicAccountStateCache ::CacheValueType CacheValueType
Definition: SynchronizedCache.h:204
catapult::cache::SynchronizedCache::m_commitCounter
size_t m_commitCounter
Definition: SynchronizedCache.h:266
CATAPULT_THROW_RUNTIME_ERROR
#define CATAPULT_THROW_RUNTIME_ERROR(MESSAGE)
Macro used to throw a catapult runtime error.
Definition: exceptions.h:167
catapult::cache::detail::CacheViewAccessor::operator->
TCacheView * operator->()
Gets a pointer to the underlying cache view.
Definition: SynchronizedCache.h:80
catapult::utils::BasicSpinReaderWriterLock::ReaderLockGuard
A reader lock guard.
Definition: SpinReaderWriterLock.h:99
catapult::cache::detail::CacheViewReadLockPair::CacheViewReadLockPair
CacheViewReadLockPair(TCacheView &&cacheView, utils::SpinReaderWriterLock::ReaderLockGuard &&readLock)
Creates a pair around cacheView and readLock.
Definition: SynchronizedCache.h:37
catapult::cache::LockedCacheDelta::m_pPair
std::shared_ptr< detail::CacheViewReadLockPair< TCacheView > > m_pPair
Definition: SynchronizedCache.h:138
catapult::cache::LockedCacheView::m_cacheView
TCacheView m_cacheView
Definition: SynchronizedCache.h:119
catapult::cache::detail::CacheViewAccessor::operator*
const TCacheView & operator*() const
Gets a const reference to the underlying cache view.
Definition: SynchronizedCache.h:74
catapult::cache::SynchronizedCache::m_pWeakDeltaPair
std::weak_ptr< detail::CacheViewReadLockPair< CacheDeltaType > > m_pWeakDeltaPair
Definition: SynchronizedCache.h:267
catapult
Definition: AddressExtractionExtension.cpp:28
catapult::cache::SynchronizedCache::createDetachedDelta
LockableCacheDelta< CacheDeltaType > createDetachedDelta() const
Definition: SynchronizedCache.h:241
catapult::cache::SynchronizedCache::createDelta
LockedCacheDelta< CacheDeltaType > createDelta()
Definition: SynchronizedCache.h:225
catapult::cache::detail::CacheViewReadLockPair
Definition: SynchronizedCache.h:34
catapult::cache::OptionalLockedCacheDelta
An optional cache-delta, read-lock pair.
Definition: SynchronizedCache.h:147
catapult::utils::BasicSpinReaderWriterLock
Definition: SpinReaderWriterLock.h:36
catapult::cache::SynchronizedCacheWithInit::SynchronizedCacheWithInit
SynchronizedCacheWithInit(TCache &&cache)
Creates a synchronized decorator around cache.
Definition: SynchronizedCache.h:280
catapult::cache::SynchronizedCacheWithInit::init
void init(TArgs &&... args)
Initializes the underlying cache with args.
Definition: SynchronizedCache.h:288
catapult::cache::detail::CacheViewAccessor::CacheViewAccessor
CacheViewAccessor(TCacheView *pCacheView)
Creates an accessor around pCacheView;.
Definition: SynchronizedCache.h:59
catapult::cache::LockableCacheDelta
Definition: SynchronizedCache.h:168
NonCopyable.h