Incorporate SharedAssetDepot changes from asset-endpoint-as-shared-asset
This commit is contained in:
parent
f58293707c
commit
68f9206141
|
|
@ -23,16 +23,39 @@ template <typename T> class SharedAsset;
|
|||
|
||||
namespace CesiumAsync {
|
||||
|
||||
/**
|
||||
* @brief The default context passed to \ref SharedAssetDepot factory functions.
|
||||
*/
|
||||
struct SharedAssetContext {
|
||||
/**
|
||||
* @brief The async system.
|
||||
*/
|
||||
AsyncSystem asyncSystem;
|
||||
|
||||
/**
|
||||
* @brief The asset accessor.
|
||||
*/
|
||||
std::shared_ptr<IAssetAccessor> pAssetAccessor;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief A depot for {@link CesiumUtility::SharedAsset} instances, which are potentially shared between multiple objects.
|
||||
*
|
||||
* @tparam TAssetType The type of asset stored in this depot. This should
|
||||
* be derived from {@link CesiumUtility::SharedAsset}.
|
||||
* @tparam TAssetKey The key type used to uniquely identify assets in this
|
||||
* depot.
|
||||
* @tparam TContext The type of context passed to the factory function when
|
||||
* creating a new asset. This defaults to \ref SharedAssetContext. This type
|
||||
* must contain a field named `asyncSystem` of type \ref AsyncSystem.
|
||||
*/
|
||||
template <typename TAssetType, typename TAssetKey>
|
||||
template <
|
||||
typename TAssetType,
|
||||
typename TAssetKey,
|
||||
typename TContext = SharedAssetContext>
|
||||
class CESIUMASYNC_API SharedAssetDepot
|
||||
: public CesiumUtility::ReferenceCountedThreadSafe<
|
||||
SharedAssetDepot<TAssetType, TAssetKey>>,
|
||||
SharedAssetDepot<TAssetType, TAssetKey, TContext>>,
|
||||
public CesiumUtility::IDepotOwningAsset<TAssetType> {
|
||||
public:
|
||||
/**
|
||||
|
|
@ -66,8 +89,7 @@ public:
|
|||
*/
|
||||
using FactorySignature =
|
||||
CesiumAsync::Future<CesiumUtility::ResultPointer<TAssetType>>(
|
||||
const AsyncSystem& asyncSystem,
|
||||
const std::shared_ptr<IAssetAccessor>& pAssetAccessor,
|
||||
const TContext& context,
|
||||
const TAssetKey& key);
|
||||
|
||||
/**
|
||||
|
|
@ -85,16 +107,12 @@ public:
|
|||
* @brief Gets an asset from the depot if it already exists, or creates it
|
||||
* using the depot's factory if it does not.
|
||||
*
|
||||
* @param asyncSystem The async system.
|
||||
* @param pAssetAccessor The asset accessor to use to download assets, if
|
||||
* necessary.
|
||||
* @param context The context to pass to the factory function.
|
||||
* @param assetKey The key uniquely identifying the asset to get or create.
|
||||
* @return A shared future that resolves when the asset is ready or fails.
|
||||
*/
|
||||
SharedFuture<CesiumUtility::ResultPointer<TAssetType>> getOrCreate(
|
||||
const AsyncSystem& asyncSystem,
|
||||
const std::shared_ptr<IAssetAccessor>& pAssetAccessor,
|
||||
const TAssetKey& assetKey);
|
||||
SharedFuture<CesiumUtility::ResultPointer<TAssetType>>
|
||||
getOrCreate(const TContext& context, const TAssetKey& assetKey);
|
||||
|
||||
/**
|
||||
* @brief Invalidates the previously-cached asset with the given key, so that
|
||||
|
|
@ -105,8 +123,29 @@ public:
|
|||
*
|
||||
* If an asset with the given key does not exist in the depot, this method
|
||||
* does nothing.
|
||||
*
|
||||
* @param assetKey The asset key to invalidate.
|
||||
* @returns True if the asset was invalidated; false if the asset key does not
|
||||
* exist in the depot or was already invalidated.
|
||||
*/
|
||||
void invalidate(const TAssetKey& assetKey);
|
||||
bool invalidate(const TAssetKey& assetKey);
|
||||
|
||||
/**
|
||||
* @brief Invalidates the previously-cached asset, so that the next call to
|
||||
* {@link getOrCreate} will create the asset instead of returning the existing
|
||||
* one.
|
||||
*
|
||||
* Anyone already using the existing asset may continue to do so.
|
||||
*
|
||||
* If the asset is not associated with the depot, or if it has already been
|
||||
* invalidated, this method does nothing. If another asset with the same key
|
||||
* already exists in the depot, invalidating this one will not affect it.
|
||||
*
|
||||
* @param asset The asset to invalidate.
|
||||
* @returns True if the asset was invalidated; false if the asset is not owned
|
||||
* by the depot or was already invalidated.
|
||||
*/
|
||||
bool invalidate(TAssetType& asset);
|
||||
|
||||
/**
|
||||
* @brief Returns the total number of distinct assets contained in this depot,
|
||||
|
|
@ -133,7 +172,8 @@ public:
|
|||
int64_t getInactiveAssetTotalSizeBytes() const;
|
||||
|
||||
// Disable copy
|
||||
void operator=(const SharedAssetDepot<TAssetType, TAssetKey>& other) = delete;
|
||||
void operator=(
|
||||
const SharedAssetDepot<TAssetType, TAssetKey, TContext>& other) = delete;
|
||||
|
||||
private:
|
||||
struct LockHolder;
|
||||
|
|
@ -172,6 +212,14 @@ private:
|
|||
|
||||
void unmarkDeletionCandidateUnderLock(const TAssetType& asset);
|
||||
|
||||
/**
|
||||
* @brief Invalidates the asset with the given key.
|
||||
*
|
||||
* The depot lock must be held when this is called, and it will be released by
|
||||
* the time this method returns.
|
||||
*/
|
||||
bool invalidateUnderLock(LockHolder&& lock, const TAssetKey& assetKey);
|
||||
|
||||
/**
|
||||
* @brief An entry for an asset owned by this depot. This is reference counted
|
||||
* so that we can keep it alive during async operations.
|
||||
|
|
@ -282,12 +330,13 @@ private:
|
|||
// This instance keeps a reference to itself whenever it is managing active
|
||||
// assets, preventing it from being destroyed even if all other references to
|
||||
// it are dropped.
|
||||
CesiumUtility::IntrusivePointer<SharedAssetDepot<TAssetType, TAssetKey>>
|
||||
CesiumUtility::IntrusivePointer<
|
||||
SharedAssetDepot<TAssetType, TAssetKey, TContext>>
|
||||
_pKeepAlive;
|
||||
};
|
||||
|
||||
template <typename TAssetType, typename TAssetKey>
|
||||
SharedAssetDepot<TAssetType, TAssetKey>::SharedAssetDepot(
|
||||
template <typename TAssetType, typename TAssetKey, typename TContext>
|
||||
SharedAssetDepot<TAssetType, TAssetKey, TContext>::SharedAssetDepot(
|
||||
std::function<FactorySignature> factory)
|
||||
: _assets(),
|
||||
_assetsByPointer(),
|
||||
|
|
@ -298,8 +347,8 @@ SharedAssetDepot<TAssetType, TAssetKey>::SharedAssetDepot(
|
|||
_factory(std::move(factory)),
|
||||
_pKeepAlive(nullptr) {}
|
||||
|
||||
template <typename TAssetType, typename TAssetKey>
|
||||
SharedAssetDepot<TAssetType, TAssetKey>::~SharedAssetDepot() {
|
||||
template <typename TAssetType, typename TAssetKey, typename TContext>
|
||||
SharedAssetDepot<TAssetType, TAssetKey, TContext>::~SharedAssetDepot() {
|
||||
// Ideally, when the depot is destroyed, all the assets it owns would become
|
||||
// independent assets. But this is extremely difficult to manage in a
|
||||
// thread-safe manner.
|
||||
|
|
@ -325,11 +374,10 @@ SharedAssetDepot<TAssetType, TAssetKey>::~SharedAssetDepot() {
|
|||
CESIUM_ASSERT(this->_assets.size() == this->_deletionCandidates.size());
|
||||
}
|
||||
|
||||
template <typename TAssetType, typename TAssetKey>
|
||||
template <typename TAssetType, typename TAssetKey, typename TContext>
|
||||
SharedFuture<CesiumUtility::ResultPointer<TAssetType>>
|
||||
SharedAssetDepot<TAssetType, TAssetKey>::getOrCreate(
|
||||
const AsyncSystem& asyncSystem,
|
||||
const std::shared_ptr<IAssetAccessor>& pAssetAccessor,
|
||||
SharedAssetDepot<TAssetType, TAssetKey, TContext>::getOrCreate(
|
||||
const TContext& context,
|
||||
const TAssetKey& assetKey) {
|
||||
// We need to take care here to avoid two assets starting to load before the
|
||||
// first asset has added an entry and set its maybePendingAsset field.
|
||||
|
|
@ -344,7 +392,7 @@ SharedAssetDepot<TAssetType, TAssetKey>::getOrCreate(
|
|||
// Asset is currently loading.
|
||||
return *entry.maybePendingAsset;
|
||||
} else {
|
||||
return asyncSystem.createResolvedFuture(entry.toResultUnderLock())
|
||||
return context.asyncSystem.createResolvedFuture(entry.toResultUnderLock())
|
||||
.share();
|
||||
}
|
||||
}
|
||||
|
|
@ -358,18 +406,19 @@ SharedAssetDepot<TAssetType, TAssetKey>::getOrCreate(
|
|||
// So we jump through some hoops here to publish "this thread is working
|
||||
// on it", then unlock the mutex, and _then_ actually call the factory
|
||||
// function.
|
||||
Promise<void> promise = asyncSystem.createPromise<void>();
|
||||
Promise<void> promise = context.asyncSystem.template createPromise<void>();
|
||||
|
||||
// We haven't loaded or started to load this asset yet.
|
||||
// Let's do that now.
|
||||
CesiumUtility::IntrusivePointer<SharedAssetDepot<TAssetType, TAssetKey>>
|
||||
CesiumUtility::IntrusivePointer<
|
||||
SharedAssetDepot<TAssetType, TAssetKey, TContext>>
|
||||
pDepot = this;
|
||||
CesiumUtility::IntrusivePointer<AssetEntry> pEntry = new AssetEntry(assetKey);
|
||||
|
||||
auto future =
|
||||
promise.getFuture()
|
||||
.thenImmediately([pDepot, pEntry, asyncSystem, pAssetAccessor]() {
|
||||
return pDepot->_factory(asyncSystem, pAssetAccessor, pEntry->key);
|
||||
.thenImmediately([pDepot, pEntry, context]() {
|
||||
return pDepot->_factory(context, pEntry->key);
|
||||
})
|
||||
.catchImmediately([](std::exception&& e) {
|
||||
return CesiumUtility::Result<
|
||||
|
|
@ -421,80 +470,65 @@ SharedAssetDepot<TAssetType, TAssetKey>::getOrCreate(
|
|||
return sharedFuture;
|
||||
}
|
||||
|
||||
template <typename TAssetType, typename TAssetKey>
|
||||
void SharedAssetDepot<TAssetType, TAssetKey>::invalidate(
|
||||
template <typename TAssetType, typename TAssetKey, typename TContext>
|
||||
bool SharedAssetDepot<TAssetType, TAssetKey, TContext>::invalidate(
|
||||
const TAssetKey& assetKey) {
|
||||
LockHolder lock = this->lock();
|
||||
|
||||
auto it = this->_assets.find(assetKey);
|
||||
if (it == this->_assets.end())
|
||||
return;
|
||||
|
||||
AssetEntry* pEntry = it->second.get();
|
||||
CESIUM_ASSERT(pEntry);
|
||||
|
||||
// This will remove the asset from the deletion candidates list, if it's
|
||||
// there.
|
||||
CesiumUtility::ResultPointer<TAssetType> assetResult =
|
||||
pEntry->toResultUnderLock();
|
||||
|
||||
if (assetResult.pValue) {
|
||||
if (!assetResult.pValue->_isInvalidated) {
|
||||
assetResult.pValue->_isInvalidated = true;
|
||||
++this->_liveInvalidatedAssets;
|
||||
}
|
||||
this->_assetsByPointer.erase(assetResult.pValue.get());
|
||||
}
|
||||
|
||||
// Detach the asset from the AssetEntry, so that its lifetime is controlled by
|
||||
// reference counting.
|
||||
pEntry->pAsset.release();
|
||||
|
||||
// Remove the asset entry. This won't immediately delete the asset, because
|
||||
// `assetResult` above still holds a reference to it. But once that goes out
|
||||
// of scope, too, the asset _may_ be destroyed.
|
||||
this->_assets.erase(it);
|
||||
|
||||
// Unlock the mutex before allowing `assetResult` to go out of scope. When it
|
||||
// goes out of scope, the asset may be destroyed. If it is, that would cause
|
||||
// us to try to re-enter the lock, which is not allowed.
|
||||
lock.unlock();
|
||||
return this->invalidateUnderLock(std::move(lock), assetKey);
|
||||
}
|
||||
|
||||
template <typename TAssetType, typename TAssetKey>
|
||||
size_t SharedAssetDepot<TAssetType, TAssetKey>::getAssetCount() const {
|
||||
template <typename TAssetType, typename TAssetKey, typename TContext>
|
||||
bool SharedAssetDepot<TAssetType, TAssetKey, TContext>::invalidate(
|
||||
TAssetType& asset) {
|
||||
LockHolder lock = this->lock();
|
||||
|
||||
auto it = this->_assetsByPointer.find(&asset);
|
||||
if (it == this->_assetsByPointer.end())
|
||||
return false;
|
||||
|
||||
AssetEntry* pEntry = it->second;
|
||||
CESIUM_ASSERT(pEntry);
|
||||
|
||||
return this->invalidateUnderLock(std::move(lock), pEntry->key);
|
||||
}
|
||||
|
||||
template <typename TAssetType, typename TAssetKey, typename TContext>
|
||||
size_t
|
||||
SharedAssetDepot<TAssetType, TAssetKey, TContext>::getAssetCount() const {
|
||||
LockHolder lock = this->lock();
|
||||
return this->_assets.size();
|
||||
}
|
||||
|
||||
template <typename TAssetType, typename TAssetKey>
|
||||
size_t SharedAssetDepot<TAssetType, TAssetKey>::getActiveAssetCount() const {
|
||||
template <typename TAssetType, typename TAssetKey, typename TContext>
|
||||
size_t
|
||||
SharedAssetDepot<TAssetType, TAssetKey, TContext>::getActiveAssetCount() const {
|
||||
LockHolder lock = this->lock();
|
||||
return this->_assets.size() - this->_deletionCandidates.size();
|
||||
}
|
||||
|
||||
template <typename TAssetType, typename TAssetKey>
|
||||
size_t SharedAssetDepot<TAssetType, TAssetKey>::getInactiveAssetCount() const {
|
||||
template <typename TAssetType, typename TAssetKey, typename TContext>
|
||||
size_t
|
||||
SharedAssetDepot<TAssetType, TAssetKey, TContext>::getInactiveAssetCount()
|
||||
const {
|
||||
LockHolder lock = this->lock();
|
||||
return this->_deletionCandidates.size();
|
||||
}
|
||||
|
||||
template <typename TAssetType, typename TAssetKey>
|
||||
int64_t
|
||||
SharedAssetDepot<TAssetType, TAssetKey>::getInactiveAssetTotalSizeBytes()
|
||||
const {
|
||||
template <typename TAssetType, typename TAssetKey, typename TContext>
|
||||
int64_t SharedAssetDepot<TAssetType, TAssetKey, TContext>::
|
||||
getInactiveAssetTotalSizeBytes() const {
|
||||
LockHolder lock = this->lock();
|
||||
return this->_totalDeletionCandidateMemoryUsage;
|
||||
}
|
||||
|
||||
template <typename TAssetType, typename TAssetKey>
|
||||
typename SharedAssetDepot<TAssetType, TAssetKey>::LockHolder
|
||||
SharedAssetDepot<TAssetType, TAssetKey>::lock() const {
|
||||
template <typename TAssetType, typename TAssetKey, typename TContext>
|
||||
typename SharedAssetDepot<TAssetType, TAssetKey, TContext>::LockHolder
|
||||
SharedAssetDepot<TAssetType, TAssetKey, TContext>::lock() const {
|
||||
return LockHolder{this};
|
||||
}
|
||||
|
||||
template <typename TAssetType, typename TAssetKey>
|
||||
void SharedAssetDepot<TAssetType, TAssetKey>::markDeletionCandidate(
|
||||
template <typename TAssetType, typename TAssetKey, typename TContext>
|
||||
void SharedAssetDepot<TAssetType, TAssetKey, TContext>::markDeletionCandidate(
|
||||
const TAssetType& asset,
|
||||
bool threadOwnsDepotLock) {
|
||||
if (threadOwnsDepotLock) {
|
||||
|
|
@ -505,9 +539,9 @@ void SharedAssetDepot<TAssetType, TAssetKey>::markDeletionCandidate(
|
|||
}
|
||||
}
|
||||
|
||||
template <typename TAssetType, typename TAssetKey>
|
||||
void SharedAssetDepot<TAssetType, TAssetKey>::markDeletionCandidateUnderLock(
|
||||
const TAssetType& asset) {
|
||||
template <typename TAssetType, typename TAssetKey, typename TContext>
|
||||
void SharedAssetDepot<TAssetType, TAssetKey, TContext>::
|
||||
markDeletionCandidateUnderLock(const TAssetType& asset) {
|
||||
if (asset._isInvalidated) {
|
||||
// This asset is no longer tracked by the depot, so delete it.
|
||||
--this->_liveInvalidatedAssets;
|
||||
|
|
@ -575,8 +609,8 @@ void SharedAssetDepot<TAssetType, TAssetKey>::markDeletionCandidateUnderLock(
|
|||
}
|
||||
}
|
||||
|
||||
template <typename TAssetType, typename TAssetKey>
|
||||
void SharedAssetDepot<TAssetType, TAssetKey>::unmarkDeletionCandidate(
|
||||
template <typename TAssetType, typename TAssetKey, typename TContext>
|
||||
void SharedAssetDepot<TAssetType, TAssetKey, TContext>::unmarkDeletionCandidate(
|
||||
const TAssetType& asset,
|
||||
bool threadOwnsDepotLock) {
|
||||
if (threadOwnsDepotLock) {
|
||||
|
|
@ -587,9 +621,9 @@ void SharedAssetDepot<TAssetType, TAssetKey>::unmarkDeletionCandidate(
|
|||
}
|
||||
}
|
||||
|
||||
template <typename TAssetType, typename TAssetKey>
|
||||
void SharedAssetDepot<TAssetType, TAssetKey>::unmarkDeletionCandidateUnderLock(
|
||||
const TAssetType& asset) {
|
||||
template <typename TAssetType, typename TAssetKey, typename TContext>
|
||||
void SharedAssetDepot<TAssetType, TAssetKey, TContext>::
|
||||
unmarkDeletionCandidateUnderLock(const TAssetType& asset) {
|
||||
// This asset better not already be invalidated. That would imply this asset
|
||||
// was resurrected after its reference count hit zero. This should only be
|
||||
// possible if the asset depot returned a pointer to the asset, which it
|
||||
|
|
@ -618,9 +652,54 @@ void SharedAssetDepot<TAssetType, TAssetKey>::unmarkDeletionCandidateUnderLock(
|
|||
this->_pKeepAlive = this;
|
||||
}
|
||||
|
||||
template <typename TAssetType, typename TAssetKey>
|
||||
template <typename TAssetType, typename TAssetKey, typename TContext>
|
||||
bool SharedAssetDepot<TAssetType, TAssetKey, TContext>::invalidateUnderLock(
|
||||
LockHolder&& lock,
|
||||
const TAssetKey& assetKey) {
|
||||
auto it = this->_assets.find(assetKey);
|
||||
if (it == this->_assets.end())
|
||||
return false;
|
||||
|
||||
AssetEntry* pEntry = it->second.get();
|
||||
CESIUM_ASSERT(pEntry);
|
||||
|
||||
// This will remove the asset from the deletion candidates list, if it's
|
||||
// there.
|
||||
CesiumUtility::ResultPointer<TAssetType> assetResult =
|
||||
pEntry->toResultUnderLock();
|
||||
|
||||
bool wasInvalidated = false;
|
||||
|
||||
if (assetResult.pValue) {
|
||||
if (!assetResult.pValue->_isInvalidated) {
|
||||
wasInvalidated = true;
|
||||
assetResult.pValue->_isInvalidated = true;
|
||||
++this->_liveInvalidatedAssets;
|
||||
}
|
||||
this->_assetsByPointer.erase(assetResult.pValue.get());
|
||||
}
|
||||
|
||||
// Detach the asset from the AssetEntry, so that its lifetime is controlled by
|
||||
// reference counting.
|
||||
pEntry->pAsset.release();
|
||||
|
||||
// Remove the asset entry. This won't immediately delete the asset, because
|
||||
// `assetResult` above still holds a reference to it. But once that goes out
|
||||
// of scope, too, the asset _may_ be destroyed.
|
||||
this->_assets.erase(it);
|
||||
|
||||
// Unlock the mutex before allowing `assetResult` to go out of scope. When it
|
||||
// goes out of scope, the asset may be destroyed. If it is, that would cause
|
||||
// us to try to re-enter the lock, which is not allowed.
|
||||
lock.unlock();
|
||||
|
||||
return wasInvalidated;
|
||||
}
|
||||
|
||||
template <typename TAssetType, typename TAssetKey, typename TContext>
|
||||
CesiumUtility::ResultPointer<TAssetType>
|
||||
SharedAssetDepot<TAssetType, TAssetKey>::AssetEntry::toResultUnderLock() const {
|
||||
SharedAssetDepot<TAssetType, TAssetKey, TContext>::AssetEntry::
|
||||
toResultUnderLock() const {
|
||||
// This method is called while the calling thread already owns the depot
|
||||
// mutex. So we must take care not to lock it again, which could happen if
|
||||
// the asset is currently unreferenced and we naively create an
|
||||
|
|
@ -634,16 +713,17 @@ SharedAssetDepot<TAssetType, TAssetKey>::AssetEntry::toResultUnderLock() const {
|
|||
return CesiumUtility::ResultPointer<TAssetType>(p, errorsAndWarnings);
|
||||
}
|
||||
|
||||
template <typename TAssetType, typename TAssetKey>
|
||||
SharedAssetDepot<TAssetType, TAssetKey>::LockHolder::LockHolder(
|
||||
template <typename TAssetType, typename TAssetKey, typename TContext>
|
||||
SharedAssetDepot<TAssetType, TAssetKey, TContext>::LockHolder::LockHolder(
|
||||
const CesiumUtility::IntrusivePointer<const SharedAssetDepot>& pDepot_)
|
||||
: pDepot(pDepot_), lock(pDepot_->_mutex) {}
|
||||
|
||||
template <typename TAssetType, typename TAssetKey>
|
||||
SharedAssetDepot<TAssetType, TAssetKey>::LockHolder::~LockHolder() = default;
|
||||
template <typename TAssetType, typename TAssetKey, typename TContext>
|
||||
SharedAssetDepot<TAssetType, TAssetKey, TContext>::LockHolder::~LockHolder() =
|
||||
default;
|
||||
|
||||
template <typename TAssetType, typename TAssetKey>
|
||||
void SharedAssetDepot<TAssetType, TAssetKey>::LockHolder::unlock() {
|
||||
template <typename TAssetType, typename TAssetKey, typename TContext>
|
||||
void SharedAssetDepot<TAssetType, TAssetKey, TContext>::LockHolder::unlock() {
|
||||
this->lock.unlock();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -25,14 +25,19 @@ public:
|
|||
int64_t getSizeBytes() const { return int64_t(this->someValue.size()); }
|
||||
};
|
||||
|
||||
IntrusivePointer<SharedAssetDepot<TestAsset, std::string>> createDepot() {
|
||||
return new SharedAssetDepot<TestAsset, std::string>(
|
||||
[](const AsyncSystem& asyncSystem,
|
||||
const std::shared_ptr<IAssetAccessor>& /* pAssetAccessor */,
|
||||
const std::string& assetKey) {
|
||||
struct JustAsyncSystemContext {
|
||||
AsyncSystem asyncSystem;
|
||||
};
|
||||
|
||||
IntrusivePointer<
|
||||
SharedAssetDepot<TestAsset, std::string, JustAsyncSystemContext>>
|
||||
createDepot() {
|
||||
return new SharedAssetDepot<TestAsset, std::string, JustAsyncSystemContext>(
|
||||
[](const JustAsyncSystemContext& context, const std::string& assetKey) {
|
||||
IntrusivePointer<TestAsset> p = new TestAsset();
|
||||
p->someValue = assetKey;
|
||||
return asyncSystem.createResolvedFuture(ResultPointer<TestAsset>(p));
|
||||
return context.asyncSystem.createResolvedFuture(
|
||||
ResultPointer<TestAsset>(p));
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -42,12 +47,13 @@ TEST_CASE("SharedAssetDepot") {
|
|||
std::shared_ptr<SimpleTaskProcessor> pTaskProcessor =
|
||||
std::make_shared<SimpleTaskProcessor>();
|
||||
AsyncSystem asyncSystem(pTaskProcessor);
|
||||
JustAsyncSystemContext context{asyncSystem};
|
||||
|
||||
SUBCASE("getOrCreate can create assets") {
|
||||
auto pDepot = createDepot();
|
||||
|
||||
ResultPointer<TestAsset> assetOne =
|
||||
pDepot->getOrCreate(asyncSystem, nullptr, "one").waitInMainThread();
|
||||
pDepot->getOrCreate(context, "one").waitInMainThread();
|
||||
|
||||
REQUIRE(assetOne.pValue != nullptr);
|
||||
}
|
||||
|
|
@ -56,8 +62,8 @@ TEST_CASE("SharedAssetDepot") {
|
|||
"the same key") {
|
||||
auto pDepot = createDepot();
|
||||
|
||||
auto futureOne = pDepot->getOrCreate(asyncSystem, nullptr, "one");
|
||||
auto futureTwo = pDepot->getOrCreate(asyncSystem, nullptr, "one");
|
||||
auto futureOne = pDepot->getOrCreate(context, "one");
|
||||
auto futureTwo = pDepot->getOrCreate(context, "one");
|
||||
|
||||
ResultPointer<TestAsset> assetOne = futureOne.waitInMainThread();
|
||||
ResultPointer<TestAsset> assetTwo = futureTwo.waitInMainThread();
|
||||
|
|
@ -70,7 +76,7 @@ TEST_CASE("SharedAssetDepot") {
|
|||
auto pDepot = createDepot();
|
||||
|
||||
ResultPointer<TestAsset> assetOne =
|
||||
pDepot->getOrCreate(asyncSystem, nullptr, "one").waitInMainThread();
|
||||
pDepot->getOrCreate(context, "one").waitInMainThread();
|
||||
|
||||
CHECK(pDepot->getAssetCount() == 1);
|
||||
CHECK(pDepot->getActiveAssetCount() == 1);
|
||||
|
|
@ -87,7 +93,7 @@ TEST_CASE("SharedAssetDepot") {
|
|||
auto pDepot = createDepot();
|
||||
|
||||
ResultPointer<TestAsset> assetOne =
|
||||
pDepot->getOrCreate(asyncSystem, nullptr, "one").waitInMainThread();
|
||||
pDepot->getOrCreate(context, "one").waitInMainThread();
|
||||
|
||||
CHECK(pDepot->getAssetCount() == 1);
|
||||
CHECK(pDepot->getActiveAssetCount() == 1);
|
||||
|
|
@ -100,7 +106,7 @@ TEST_CASE("SharedAssetDepot") {
|
|||
CHECK(pDepot->getInactiveAssetCount() == 1);
|
||||
|
||||
ResultPointer<TestAsset> assetTwo =
|
||||
pDepot->getOrCreate(asyncSystem, nullptr, "one").waitInMainThread();
|
||||
pDepot->getOrCreate(context, "one").waitInMainThread();
|
||||
|
||||
CHECK(pDepot->getAssetCount() == 1);
|
||||
CHECK(pDepot->getActiveAssetCount() == 1);
|
||||
|
|
@ -114,9 +120,9 @@ TEST_CASE("SharedAssetDepot") {
|
|||
int64_t(std::string("one").size() + 1);
|
||||
|
||||
ResultPointer<TestAsset> assetOne =
|
||||
pDepot->getOrCreate(asyncSystem, nullptr, "one").waitInMainThread();
|
||||
pDepot->getOrCreate(context, "one").waitInMainThread();
|
||||
ResultPointer<TestAsset> assetTwo =
|
||||
pDepot->getOrCreate(asyncSystem, nullptr, "two").waitInMainThread();
|
||||
pDepot->getOrCreate(context, "two").waitInMainThread();
|
||||
|
||||
assetOne.pValue.reset();
|
||||
|
||||
|
|
@ -133,12 +139,13 @@ TEST_CASE("SharedAssetDepot") {
|
|||
|
||||
SUBCASE("is kept alive until all of its assets are unreferenced") {
|
||||
auto pDepot = createDepot();
|
||||
SharedAssetDepot<TestAsset, std::string>* pDepotRaw = pDepot.get();
|
||||
SharedAssetDepot<TestAsset, std::string, JustAsyncSystemContext>*
|
||||
pDepotRaw = pDepot.get();
|
||||
|
||||
ResultPointer<TestAsset> assetOne =
|
||||
pDepot->getOrCreate(asyncSystem, nullptr, "one").waitInMainThread();
|
||||
pDepot->getOrCreate(context, "one").waitInMainThread();
|
||||
ResultPointer<TestAsset> assetTwo =
|
||||
pDepot->getOrCreate(asyncSystem, nullptr, "two!!").waitInMainThread();
|
||||
pDepot->getOrCreate(context, "two!!").waitInMainThread();
|
||||
|
||||
pDepot.reset();
|
||||
|
||||
|
|
@ -156,14 +163,14 @@ TEST_CASE("SharedAssetDepot") {
|
|||
auto pDepot = createDepot();
|
||||
|
||||
ResultPointer<TestAsset> assetOne =
|
||||
pDepot->getOrCreate(asyncSystem, nullptr, "one").waitInMainThread();
|
||||
pDepot->getOrCreate(context, "one").waitInMainThread();
|
||||
|
||||
REQUIRE(assetOne.pValue != nullptr);
|
||||
|
||||
pDepot->invalidate("one");
|
||||
|
||||
ResultPointer<TestAsset> assetOne2 =
|
||||
pDepot->getOrCreate(asyncSystem, nullptr, "one").waitInMainThread();
|
||||
pDepot->getOrCreate(context, "one").waitInMainThread();
|
||||
|
||||
REQUIRE(assetOne.pValue != assetOne2.pValue);
|
||||
CHECK(assetOne.pValue->someValue == "one");
|
||||
|
|
@ -172,10 +179,11 @@ TEST_CASE("SharedAssetDepot") {
|
|||
|
||||
SUBCASE("is kept alive for as long as invalidated assets are alive") {
|
||||
auto pDepot = createDepot();
|
||||
SharedAssetDepot<TestAsset, std::string>* pDepotRaw = pDepot.get();
|
||||
SharedAssetDepot<TestAsset, std::string, JustAsyncSystemContext>*
|
||||
pDepotRaw = pDepot.get();
|
||||
|
||||
ResultPointer<TestAsset> assetOne =
|
||||
pDepot->getOrCreate(asyncSystem, nullptr, "one").waitInMainThread();
|
||||
pDepot->getOrCreate(context, "one").waitInMainThread();
|
||||
|
||||
REQUIRE(assetOne.pValue != nullptr);
|
||||
|
||||
|
|
@ -193,7 +201,7 @@ TEST_CASE("SharedAssetDepot") {
|
|||
auto pDepot = createDepot();
|
||||
|
||||
ResultPointer<TestAsset> assetOne =
|
||||
pDepot->getOrCreate(asyncSystem, nullptr, "one").waitInMainThread();
|
||||
pDepot->getOrCreate(context, "one").waitInMainThread();
|
||||
|
||||
REQUIRE(assetOne.pValue != nullptr);
|
||||
assetOne.pValue.reset();
|
||||
|
|
@ -212,7 +220,7 @@ TEST_CASE("SharedAssetDepot") {
|
|||
auto pDepot = createDepot();
|
||||
|
||||
ResultPointer<TestAsset> assetOne =
|
||||
pDepot->getOrCreate(asyncSystem, nullptr, "one").waitInMainThread();
|
||||
pDepot->getOrCreate(context, "one").waitInMainThread();
|
||||
|
||||
REQUIRE(assetOne.pValue != nullptr);
|
||||
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@
|
|||
#include <CesiumAsync/IAssetAccessor.h>
|
||||
#include <CesiumAsync/IAssetRequest.h>
|
||||
#include <CesiumAsync/IAssetResponse.h>
|
||||
#include <CesiumAsync/SharedAssetDepot.h>
|
||||
#include <CesiumAsync/SharedFuture.h>
|
||||
#include <CesiumGltf/Buffer.h>
|
||||
#include <CesiumGltf/BufferView.h>
|
||||
|
|
@ -596,8 +597,9 @@ void CesiumGltfReader::GltfReader::postprocessGltf(
|
|||
} else {
|
||||
// We have a depot, so fetch this asset via that depot.
|
||||
return options.pSharedAssetSystem->pImage->getOrCreate(
|
||||
asyncSystem,
|
||||
pAssetAccessor,
|
||||
SharedAssetContext{
|
||||
.asyncSystem = asyncSystem,
|
||||
.pAssetAccessor = pAssetAccessor},
|
||||
assetKey);
|
||||
}
|
||||
};
|
||||
|
|
@ -643,8 +645,9 @@ void CesiumGltfReader::GltfReader::postprocessGltf(
|
|||
} else {
|
||||
// We have a depot, so fetch this asset via that depot.
|
||||
return options.pSharedAssetSystem->pExternalMetadataSchema->getOrCreate(
|
||||
asyncSystem,
|
||||
pAssetAccessor,
|
||||
SharedAssetContext{
|
||||
.asyncSystem = asyncSystem,
|
||||
.pAssetAccessor = pAssetAccessor},
|
||||
assetKey);
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
#include <CesiumAsync/AsyncSystem.h>
|
||||
#include <CesiumAsync/Future.h>
|
||||
#include <CesiumAsync/IAssetAccessor.h>
|
||||
#include <CesiumAsync/SharedAssetDepot.h>
|
||||
#include <CesiumGltf/ImageAsset.h>
|
||||
#include <CesiumGltf/Schema.h>
|
||||
#include <CesiumGltfReader/GltfSharedAssetSystem.h>
|
||||
|
|
@ -10,7 +10,6 @@
|
|||
#include <CesiumUtility/Result.h>
|
||||
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
|
||||
using namespace CesiumAsync;
|
||||
using namespace CesiumGltf;
|
||||
|
|
@ -24,19 +23,17 @@ CesiumUtility::IntrusivePointer<GltfSharedAssetSystem> createDefault() {
|
|||
new GltfSharedAssetSystem();
|
||||
|
||||
p->pImage.emplace(std::function(
|
||||
[](const AsyncSystem& asyncSystem,
|
||||
const std::shared_ptr<IAssetAccessor>& pAssetAccessor,
|
||||
[](const SharedAssetContext& context,
|
||||
const NetworkImageAssetDescriptor& key)
|
||||
-> Future<ResultPointer<ImageAsset>> {
|
||||
return key.load(asyncSystem, pAssetAccessor);
|
||||
return key.load(context.asyncSystem, context.pAssetAccessor);
|
||||
}));
|
||||
|
||||
p->pExternalMetadataSchema.emplace(std::function(
|
||||
[](const AsyncSystem& asyncSystem,
|
||||
const std::shared_ptr<IAssetAccessor>& pAssetAccessor,
|
||||
[](const SharedAssetContext& context,
|
||||
const NetworkSchemaAssetDescriptor& key)
|
||||
-> Future<ResultPointer<Schema>> {
|
||||
return key.load(asyncSystem, pAssetAccessor);
|
||||
return key.load(context.asyncSystem, context.pAssetAccessor);
|
||||
}));
|
||||
|
||||
return p;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
#include <CesiumAsync/AsyncSystem.h>
|
||||
#include <CesiumAsync/Future.h>
|
||||
#include <CesiumAsync/IAssetAccessor.h>
|
||||
#include <CesiumAsync/SharedAssetDepot.h>
|
||||
#include <CesiumAsync/SharedFuture.h>
|
||||
#include <CesiumGeometry/QuadtreeTileID.h>
|
||||
#include <CesiumGeometry/QuadtreeTilingScheme.h>
|
||||
|
|
@ -98,9 +99,7 @@ QuadtreeRasterOverlayTileProvider::QuadtreeRasterOverlayTileProvider(
|
|||
|
||||
this->_pTileDepot.emplace(std::function(
|
||||
[pThis = this, loadParentTile](
|
||||
const AsyncSystem& asyncSystem,
|
||||
[[maybe_unused]] const std::shared_ptr<IAssetAccessor>&
|
||||
pAssetAccessor,
|
||||
const SharedAssetContext& context,
|
||||
const QuadtreeTileID& key)
|
||||
-> Future<ResultPointer<LoadedQuadtreeImage>> {
|
||||
return pThis->loadQuadtreeTileImage(key)
|
||||
|
|
@ -115,7 +114,8 @@ QuadtreeRasterOverlayTileProvider::QuadtreeRasterOverlayTileProvider(
|
|||
key,
|
||||
currentLevel = key.level,
|
||||
minimumLevel = pThis->getMinimumLevel(),
|
||||
asyncSystem](LoadedRasterOverlayImage&& loaded)
|
||||
asyncSystem =
|
||||
context.asyncSystem](LoadedRasterOverlayImage&& loaded)
|
||||
-> Future<ResultPointer<LoadedQuadtreeImage>> {
|
||||
if (loaded.pImage && !loaded.errorList.hasErrors() &&
|
||||
loaded.pImage->width > 0 && loaded.pImage->height > 0) {
|
||||
|
|
@ -394,8 +394,9 @@ CesiumAsync::SharedFuture<
|
|||
QuadtreeRasterOverlayTileProvider::getQuadtreeTile(
|
||||
const CesiumGeometry::QuadtreeTileID& tileID) {
|
||||
return this->_pTileDepot->getOrCreate(
|
||||
this->getAsyncSystem(),
|
||||
this->getAssetAccessor(),
|
||||
SharedAssetContext{
|
||||
.asyncSystem = this->getAsyncSystem(),
|
||||
.pAssetAccessor = this->getAssetAccessor()},
|
||||
tileID);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -8,8 +8,11 @@
|
|||
#include <atomic>
|
||||
|
||||
namespace CesiumAsync {
|
||||
template <typename TAssetType, typename TAssetKey> class SharedAssetDepot;
|
||||
}
|
||||
|
||||
template <typename TAssetType, typename TAssetKey, typename TContext>
|
||||
class SharedAssetDepot;
|
||||
|
||||
} // namespace CesiumAsync
|
||||
|
||||
namespace CesiumUtility {
|
||||
|
||||
|
|
@ -152,7 +155,7 @@ private:
|
|||
bool _isInvalidated{false};
|
||||
|
||||
// To allow the depot to modify _pDepot.
|
||||
template <typename TAssetType, typename TAssetKey>
|
||||
template <typename TAssetType, typename TAssetKey, typename TContext>
|
||||
friend class CesiumAsync::SharedAssetDepot;
|
||||
friend T;
|
||||
};
|
||||
|
|
|
|||
Loading…
Reference in New Issue