133 LockHolder lock()
const;
143 void markDeletionCandidate(
const TAssetType& asset,
bool threadOwnsDepotLock)
146 void markDeletionCandidateUnderLock(
const TAssetType& asset);
156 void unmarkDeletionCandidate(
157 const TAssetType& asset,
158 bool threadOwnsDepotLock)
override;
160 void unmarkDeletionCandidateUnderLock(
const TAssetType& asset);
168 AssetEntry(TAssetKey&& key_)
170 key(
std::move(key_)),
174 sizeInDeletionList(0),
175 deletionListPointers() {}
177 AssetEntry(
const TAssetKey& key_) : AssetEntry(TAssetKey(key_)) {}
188 std::unique_ptr<TAssetType> pAsset;
195 std::optional<SharedFuture<CesiumUtility::ResultPointer<TAssetType>>>
211 int64_t sizeInDeletionList;
226 const CesiumUtility::IntrusivePointer<const SharedAssetDepot>& pDepot);
235 CesiumUtility::IntrusivePointer<const SharedAssetDepot> pDepot;
236 std::unique_lock<std::mutex> lock;
241 std::unordered_map<TAssetKey, CesiumUtility::IntrusivePointer<AssetEntry>>
246 std::unordered_map<TAssetType*, AssetEntry*> _assetsByPointer;
255 int64_t _totalDeletionCandidateMemoryUsage;
259 mutable std::mutex _mutex;
262 std::function<FactorySignature> _factory;
267 CesiumUtility::IntrusivePointer<SharedAssetDepot<TAssetType, TAssetKey>>
271template <
typename TAssetType,
typename TAssetKey>
273 std::function<FactorySignature> factory)
276 _deletionCandidates(),
277 _totalDeletionCandidateMemoryUsage(0),
279 _factory(
std::move(factory)),
280 _pKeepAlive(nullptr) {}
282template <
typename TAssetType,
typename TAssetKey>
283SharedAssetDepot<TAssetType, TAssetKey>::~SharedAssetDepot() {
305 CESIUM_ASSERT(this->_assets.size() == this->_deletionCandidates.size());
308template <
typename TAssetType,
typename TAssetKey>
309SharedFuture<CesiumUtility::ResultPointer<TAssetType>>
312 const std::shared_ptr<IAssetAccessor>& pAssetAccessor,
313 const TAssetKey& assetKey) {
316 LockHolder lock = this->lock();
318 auto existingIt = this->_assets.find(assetKey);
319 if (existingIt != this->_assets.end()) {
322 const AssetEntry& entry = *existingIt->second;
323 if (entry.maybePendingAsset) {
325 return *entry.maybePendingAsset;
351 .thenImmediately([pDepot, pEntry, asyncSystem, pAssetAccessor]() {
352 return pDepot->_factory(asyncSystem, pAssetAccessor, pEntry->key);
354 .catchImmediately([](std::exception&& e) {
358 std::string(
"Error creating asset: ") + e.what()));
364 LockHolder lock = pDepot->lock();
367 result.pValue->_pDepot = pDepot.get();
368 pDepot->_assetsByPointer[result.pValue.get()] = pEntry.
get();
374 std::unique_ptr<TAssetType>(result.pValue.get());
375 pEntry->errorsAndWarnings = std::move(result.errors);
376 pEntry->maybePendingAsset.
reset();
381 pDepot->_pKeepAlive = pDepot;
383 return pEntry->toResultUnderLock();
387 std::move(future).share();
389 pEntry->maybePendingAsset = sharedFuture;
391 [[maybe_unused]]
bool added = this->_assets.emplace(assetKey, pEntry).second;
395 CESIUM_ASSERT(added);
404template <
typename TAssetType,
typename TAssetKey>
406 LockHolder lock = this->lock();
407 return this->_assets.size();
410template <
typename TAssetType,
typename TAssetKey>
412 LockHolder lock = this->lock();
413 return this->_assets.size() - this->_deletionCandidates.size();
416template <
typename TAssetType,
typename TAssetKey>
418 LockHolder lock = this->lock();
419 return this->_deletionCandidates.size();
422template <
typename TAssetType,
typename TAssetKey>
426 LockHolder lock = this->lock();
427 return this->_totalDeletionCandidateMemoryUsage;
430template <
typename TAssetType,
typename TAssetKey>
431typename SharedAssetDepot<TAssetType, TAssetKey>::LockHolder
432SharedAssetDepot<TAssetType, TAssetKey>::lock()
const {
433 return LockHolder{
this};
436template <
typename TAssetType,
typename TAssetKey>
437void SharedAssetDepot<TAssetType, TAssetKey>::markDeletionCandidate(
438 const TAssetType& asset,
439 bool threadOwnsDepotLock) {
440 if (threadOwnsDepotLock) {
441 this->markDeletionCandidateUnderLock(asset);
443 LockHolder lock = this->lock();
444 this->markDeletionCandidateUnderLock(asset);
448template <
typename TAssetType,
typename TAssetKey>
449void SharedAssetDepot<TAssetType, TAssetKey>::markDeletionCandidateUnderLock(
450 const TAssetType& asset) {
453 if (asset._referenceCount != 0) {
457 auto it = this->_assetsByPointer.find(
const_cast<TAssetType*
>(&asset));
458 CESIUM_ASSERT(it != this->_assetsByPointer.end());
459 if (it == this->_assetsByPointer.end()) {
463 CESIUM_ASSERT(it->second !=
nullptr);
465 AssetEntry& entry = *it->second;
466 entry.sizeInDeletionList = asset.getSizeBytes();
467 this->_totalDeletionCandidateMemoryUsage += entry.sizeInDeletionList;
469 this->_deletionCandidates.insertAtTail(entry);
471 if (this->_totalDeletionCandidateMemoryUsage >
472 this->inactiveAssetSizeLimitBytes) {
474 while (this->_deletionCandidates.size() > 0 &&
475 this->_totalDeletionCandidateMemoryUsage >
476 this->inactiveAssetSizeLimitBytes) {
477 AssetEntry* pOldEntry = this->_deletionCandidates.head();
478 this->_deletionCandidates.remove(*pOldEntry);
480 this->_totalDeletionCandidateMemoryUsage -= pOldEntry->sizeInDeletionList;
483 pOldEntry->pAsset ==
nullptr ||
484 pOldEntry->pAsset->_referenceCount == 0);
486 if (pOldEntry->pAsset) {
487 this->_assetsByPointer.erase(pOldEntry->pAsset.get());
491 this->_assets.erase(pOldEntry->key);
497 if (this->_assets.size() == this->_deletionCandidates.size()) {
498 this->_pKeepAlive.reset();
502template <
typename TAssetType,
typename TAssetKey>
503void SharedAssetDepot<TAssetType, TAssetKey>::unmarkDeletionCandidate(
504 const TAssetType& asset,
505 bool threadOwnsDepotLock) {
506 if (threadOwnsDepotLock) {
507 this->unmarkDeletionCandidateUnderLock(asset);
509 LockHolder lock = this->lock();
510 this->unmarkDeletionCandidateUnderLock(asset);
514template <
typename TAssetType,
typename TAssetKey>
515void SharedAssetDepot<TAssetType, TAssetKey>::unmarkDeletionCandidateUnderLock(
516 const TAssetType& asset) {
517 auto it = this->_assetsByPointer.find(
const_cast<TAssetType*
>(&asset));
518 CESIUM_ASSERT(it != this->_assetsByPointer.end());
519 if (it == this->_assetsByPointer.end()) {
523 CESIUM_ASSERT(it->second !=
nullptr);
525 AssetEntry& entry = *it->second;
526 bool isFound = this->_deletionCandidates.contains(entry);
531 this->_totalDeletionCandidateMemoryUsage -= entry.sizeInDeletionList;
532 this->_deletionCandidates.remove(entry);
536 this->_pKeepAlive =
this;
539template <
typename TAssetType,
typename TAssetKey>
541SharedAssetDepot<TAssetType, TAssetKey>::AssetEntry::toResultUnderLock()
const {
546 CesiumUtility::IntrusivePointer<TAssetType> p =
nullptr;
548 pAsset->addReference(
true);
550 pAsset->releaseReference(
true);
555template <
typename TAssetType,
typename TAssetKey>
557 const CesiumUtility::IntrusivePointer<const SharedAssetDepot>& pDepot_)
558 : pDepot(pDepot_), lock(pDepot_->_mutex) {}
560template <
typename TAssetType,
typename TAssetKey>
561SharedAssetDepot<TAssetType, TAssetKey>::LockHolder::~LockHolder() =
default;
563template <
typename TAssetType,
typename TAssetKey>
564void SharedAssetDepot<TAssetType, TAssetKey>::LockHolder::unlock() {