mirror of
https://github.com/enduro2d/enduro2d.git
synced 2025-12-13 07:45:39 +07:00
Merge branch 'feature/asset_dependencies' into feature/gobject
This commit is contained in:
@@ -50,11 +50,10 @@ namespace e2d
|
||||
class content_asset;
|
||||
class asset;
|
||||
|
||||
template < typename T >
|
||||
class asset_cache;
|
||||
class asset_cache_base;
|
||||
|
||||
class library;
|
||||
class asset_cache;
|
||||
class asset_group;
|
||||
class asset_dependencies;
|
||||
|
||||
class atlas;
|
||||
class flipbook;
|
||||
|
||||
@@ -10,6 +10,8 @@
|
||||
|
||||
#include "_high.hpp"
|
||||
|
||||
#include "address.hpp"
|
||||
|
||||
namespace e2d
|
||||
{
|
||||
//
|
||||
@@ -22,17 +24,6 @@ namespace e2d
|
||||
}
|
||||
};
|
||||
|
||||
//
|
||||
// bad_asset_factory_operation
|
||||
//
|
||||
|
||||
class bad_asset_factory_operation final : public exception {
|
||||
public:
|
||||
const char* what() const noexcept final {
|
||||
return "bad asset factory operation";
|
||||
}
|
||||
};
|
||||
|
||||
//
|
||||
// asset
|
||||
//
|
||||
@@ -45,9 +36,9 @@ namespace e2d
|
||||
: private noncopyable
|
||||
, public ref_counter<asset> {
|
||||
public:
|
||||
asset();
|
||||
virtual ~asset() noexcept;
|
||||
virtual asset_ptr find_nested_asset(str_view name) const noexcept = 0;
|
||||
asset() = default;
|
||||
virtual ~asset() noexcept = default;
|
||||
virtual asset_ptr find_nested_asset(str_view nested_address) const noexcept = 0;
|
||||
};
|
||||
|
||||
//
|
||||
@@ -73,9 +64,9 @@ namespace e2d
|
||||
|
||||
const Content& content() const noexcept;
|
||||
|
||||
template < typename T >
|
||||
intrusive_ptr<T> find_nested_asset(str_view name) const noexcept;
|
||||
asset_ptr find_nested_asset(str_view name) const noexcept override;
|
||||
template < typename NestedAsset >
|
||||
typename NestedAsset::ptr find_nested_asset(str_view nested_address) const noexcept;
|
||||
asset_ptr find_nested_asset(str_view nested_address) const noexcept override;
|
||||
private:
|
||||
Content content_;
|
||||
nested_content nested_content_;
|
||||
@@ -87,60 +78,57 @@ namespace e2d
|
||||
|
||||
class asset_cache_base : private noncopyable {
|
||||
public:
|
||||
asset_cache_base();
|
||||
virtual ~asset_cache_base() noexcept;
|
||||
asset_cache_base() = default;
|
||||
virtual ~asset_cache_base() noexcept = default;
|
||||
|
||||
static std::size_t unload_all_unused_assets() noexcept;
|
||||
virtual std::size_t unload_self_unused_assets() noexcept = 0;
|
||||
virtual std::size_t asset_count() const noexcept = 0;
|
||||
virtual std::size_t unload_unused_assets() noexcept = 0;
|
||||
};
|
||||
|
||||
//
|
||||
// typed_asset_cache
|
||||
//
|
||||
|
||||
template < typename Asset >
|
||||
class typed_asset_cache : public asset_cache_base {
|
||||
public:
|
||||
using asset_ptr = typename Asset::ptr;
|
||||
public:
|
||||
typed_asset_cache() = default;
|
||||
~typed_asset_cache() noexcept final = default;
|
||||
|
||||
asset_ptr find(str_hash address) const noexcept;
|
||||
void store(str_hash address, const asset_ptr& asset);
|
||||
|
||||
std::size_t asset_count() const noexcept override;
|
||||
std::size_t unload_unused_assets() noexcept override;
|
||||
private:
|
||||
static std::mutex mutex_;
|
||||
static hash_set<asset_cache_base*> caches_;
|
||||
hash_map<str_hash, asset_ptr> assets_;
|
||||
};
|
||||
|
||||
//
|
||||
// asset_cache
|
||||
//
|
||||
|
||||
template < typename Asset >
|
||||
class asset_cache : public asset_cache_base
|
||||
, public module<asset_cache<Asset>> {
|
||||
class asset_cache final {
|
||||
public:
|
||||
using asset_ptr = typename Asset::ptr;
|
||||
public:
|
||||
asset_cache(library& l);
|
||||
~asset_cache() noexcept final;
|
||||
|
||||
asset_ptr find(str_hash address) const noexcept;
|
||||
void store(str_hash address, const asset_ptr& asset);
|
||||
|
||||
void clear() noexcept;
|
||||
std::size_t asset_count() const noexcept;
|
||||
|
||||
std::size_t unload_self_unused_assets() noexcept override;
|
||||
private:
|
||||
library& library_;
|
||||
mutable std::mutex mutex_;
|
||||
hash_map<str_hash, asset_ptr> assets_;
|
||||
};
|
||||
|
||||
//
|
||||
// asset_factory
|
||||
//
|
||||
|
||||
class asset_factory : public module<asset_factory> {
|
||||
public:
|
||||
using asset_creator = std::function<
|
||||
stdex::promise<asset_ptr>(const library& library, str_view address)>;
|
||||
public:
|
||||
asset_factory();
|
||||
~asset_factory() noexcept final;
|
||||
asset_cache() = default;
|
||||
~asset_cache() noexcept = default;
|
||||
|
||||
template < typename Asset >
|
||||
asset_factory& register_asset(str_hash type);
|
||||
asset_factory& register_creator(str_hash type, asset_creator creator);
|
||||
void store(str_hash address, const typename Asset::ptr& asset);
|
||||
|
||||
template < typename Asset >
|
||||
typename Asset::ptr find(str_hash address) const noexcept;
|
||||
|
||||
template < typename Asset >
|
||||
std::size_t asset_count() const noexcept;
|
||||
std::size_t asset_count() const noexcept;
|
||||
|
||||
std::size_t unload_unused_assets() noexcept;
|
||||
private:
|
||||
std::mutex mutex_;
|
||||
hash_map<str_hash, asset_creator> creators_;
|
||||
using asset_cache_uptr = std::unique_ptr<asset_cache_base>;
|
||||
hash_map<utils::type_family_id, asset_cache_uptr> caches_;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -56,33 +56,29 @@ namespace e2d
|
||||
}
|
||||
|
||||
template < typename Asset, typename Content >
|
||||
template < typename T >
|
||||
intrusive_ptr<T> content_asset<Asset, Content>::find_nested_asset(str_view name) const noexcept {
|
||||
return dynamic_pointer_cast<T>(find_nested_asset(name));
|
||||
template < typename NestedAsset >
|
||||
typename NestedAsset::ptr content_asset<Asset, Content>::find_nested_asset(str_view nested_address) const noexcept {
|
||||
return dynamic_pointer_cast<NestedAsset>(find_nested_asset(nested_address));
|
||||
}
|
||||
|
||||
template < typename Asset, typename Content >
|
||||
asset_ptr content_asset<Asset, Content>::find_nested_asset(str_view name) const noexcept {
|
||||
const auto iter = nested_content_.find(name);
|
||||
return iter != nested_content_.end()
|
||||
asset_ptr content_asset<Asset, Content>::find_nested_asset(str_view address) const noexcept {
|
||||
const auto iter = nested_content_.find(make_hash(address::parent(address)));
|
||||
if ( iter == nested_content_.end() ) {
|
||||
return nullptr;
|
||||
}
|
||||
const str nested_asset = address::nested(address);
|
||||
return nested_asset.empty()
|
||||
? iter->second
|
||||
: nullptr;
|
||||
: iter->second->find_nested_asset(nested_asset);
|
||||
}
|
||||
|
||||
//
|
||||
// asset_cache
|
||||
// typed_asset_cache
|
||||
//
|
||||
|
||||
template < typename T >
|
||||
asset_cache<T>::asset_cache(library& l)
|
||||
: library_(l) {}
|
||||
|
||||
template < typename T >
|
||||
asset_cache<T>::~asset_cache() noexcept = default;
|
||||
|
||||
template < typename T >
|
||||
typename asset_cache<T>::asset_ptr asset_cache<T>::find(str_hash address) const noexcept {
|
||||
std::lock_guard<std::mutex> guard(mutex_);
|
||||
typename typed_asset_cache<T>::asset_ptr typed_asset_cache<T>::find(str_hash address) const noexcept {
|
||||
const auto iter = assets_.find(address);
|
||||
return iter != assets_.end()
|
||||
? iter->second
|
||||
@@ -90,26 +86,17 @@ namespace e2d
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
void asset_cache<T>::store(str_hash address, const asset_ptr& asset) {
|
||||
std::lock_guard<std::mutex> guard(mutex_);
|
||||
void typed_asset_cache<T>::store(str_hash address, const asset_ptr& asset) {
|
||||
assets_[address] = asset;
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
void asset_cache<T>::clear() noexcept {
|
||||
std::lock_guard<std::mutex> guard(mutex_);
|
||||
assets_.clear();
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
std::size_t asset_cache<T>::asset_count() const noexcept {
|
||||
std::lock_guard<std::mutex> guard(mutex_);
|
||||
std::size_t typed_asset_cache<T>::asset_count() const noexcept {
|
||||
return assets_.size();
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
std::size_t asset_cache<T>::unload_self_unused_assets() noexcept {
|
||||
std::lock_guard<std::mutex> guard(mutex_);
|
||||
std::size_t typed_asset_cache<T>::unload_unused_assets() noexcept {
|
||||
std::size_t result = 0u;
|
||||
for ( auto iter = assets_.begin(); iter != assets_.end(); ) {
|
||||
if ( !iter->second || 1 == iter->second->use_count() ) {
|
||||
@@ -123,27 +110,61 @@ namespace e2d
|
||||
}
|
||||
|
||||
//
|
||||
// asset_factory
|
||||
// asset_cache
|
||||
//
|
||||
|
||||
template < typename Asset >
|
||||
asset_factory& asset_factory::register_asset(str_hash type) {
|
||||
return register_creator(type, [](const library& library, str_view address) {
|
||||
return Asset::load_async(library, address)
|
||||
.then([](const typename Asset::load_result& result){
|
||||
return static_pointer_cast<asset>(result);
|
||||
});
|
||||
});
|
||||
void asset_cache::store(str_hash address, const typename Asset::ptr& asset) {
|
||||
const auto family = utils::type_family<Asset>::id();
|
||||
const auto iter = caches_.find(family);
|
||||
typed_asset_cache<Asset>* cache = iter != caches_.end() && iter->second
|
||||
? static_cast<typed_asset_cache<Asset>*>(iter->second.get())
|
||||
: nullptr;
|
||||
if ( !cache ) {
|
||||
cache = static_cast<typed_asset_cache<Asset>*>(caches_.emplace(
|
||||
family,
|
||||
std::make_unique<typed_asset_cache<Asset>>()).first->second.get());
|
||||
}
|
||||
cache->store(address, asset);
|
||||
}
|
||||
|
||||
inline asset_factory& asset_factory::register_creator(str_hash type, asset_creator creator) {
|
||||
std::lock_guard<std::mutex> guard(mutex_);
|
||||
bool success = creators_.insert(
|
||||
std::make_pair(type, std::move(creator))).second;
|
||||
if ( !success ) {
|
||||
throw bad_asset_factory_operation();
|
||||
}
|
||||
return *this;
|
||||
template < typename Asset >
|
||||
typename Asset::ptr asset_cache::find(str_hash address) const noexcept {
|
||||
const auto iter = caches_.find(utils::type_family<Asset>::id());
|
||||
const typed_asset_cache<Asset>* cache = iter != caches_.end() && iter->second
|
||||
? static_cast<const typed_asset_cache<Asset>*>(iter->second.get())
|
||||
: nullptr;
|
||||
return cache
|
||||
? cache->find(address)
|
||||
: nullptr;
|
||||
}
|
||||
|
||||
template < typename Asset >
|
||||
std::size_t asset_cache::asset_count() const noexcept {
|
||||
const auto iter = caches_.find(utils::type_family<Asset>::id());
|
||||
return iter != caches_.end() && iter->second
|
||||
? iter->second->asset_count()
|
||||
: 0u;
|
||||
}
|
||||
|
||||
inline std::size_t asset_cache::asset_count() const noexcept {
|
||||
return std::accumulate(
|
||||
caches_.begin(), caches_.end(), std::size_t(0),
|
||||
[](std::size_t acc, const auto& p){
|
||||
return p.second
|
||||
? acc + p.second->asset_count()
|
||||
: acc;
|
||||
});
|
||||
}
|
||||
|
||||
inline std::size_t asset_cache::unload_unused_assets() noexcept {
|
||||
return std::accumulate(
|
||||
caches_.begin(), caches_.end(), std::size_t(0),
|
||||
[](std::size_t acc, const auto& p){
|
||||
return p.second
|
||||
? acc + p.second->unload_unused_assets()
|
||||
: acc;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -11,32 +11,73 @@
|
||||
#include "_high.hpp"
|
||||
|
||||
#include "asset.hpp"
|
||||
#include "address.hpp"
|
||||
|
||||
namespace e2d
|
||||
{
|
||||
//
|
||||
// bad_library_operation
|
||||
// library_cancelled_exception
|
||||
//
|
||||
|
||||
class bad_library_operation final : public exception {
|
||||
public:
|
||||
const char* what() const noexcept final {
|
||||
return "bad library operation";
|
||||
class library_cancelled_exception : public exception {
|
||||
const char* what() const noexcept override {
|
||||
return "library cancelled exception";
|
||||
}
|
||||
};
|
||||
|
||||
//
|
||||
// loading_asset_base
|
||||
//
|
||||
|
||||
class loading_asset_base;
|
||||
using loading_asset_base_iptr = intrusive_ptr<loading_asset_base>;
|
||||
|
||||
class loading_asset_base
|
||||
: private noncopyable
|
||||
, public ref_counter<loading_asset_base> {
|
||||
public:
|
||||
loading_asset_base() = default;
|
||||
virtual ~loading_asset_base() noexcept = default;
|
||||
|
||||
virtual void cancel() noexcept = 0;
|
||||
virtual str_hash address() const noexcept = 0;
|
||||
};
|
||||
|
||||
//
|
||||
// loading_asset
|
||||
//
|
||||
|
||||
template < typename Asset >
|
||||
class loading_asset : public loading_asset_base {
|
||||
public:
|
||||
using ptr = intrusive_ptr<loading_asset>;
|
||||
using promise_type = typename Asset::load_async_result;
|
||||
public:
|
||||
loading_asset(str_hash address, promise_type promise);
|
||||
~loading_asset() noexcept override = default;
|
||||
|
||||
void cancel() noexcept override;
|
||||
str_hash address() const noexcept override;
|
||||
|
||||
const promise_type& promise() const noexcept;
|
||||
private:
|
||||
str_hash address_;
|
||||
promise_type promise_;
|
||||
};
|
||||
|
||||
//
|
||||
// library
|
||||
//
|
||||
|
||||
class library final : public module<library> {
|
||||
public:
|
||||
library(const url& root);
|
||||
library(const url& root, deferrer& deferrer);
|
||||
~library() noexcept final;
|
||||
|
||||
const url& root() const noexcept;
|
||||
const asset_cache& cache() const noexcept;
|
||||
|
||||
std::size_t unload_unused_assets() noexcept;
|
||||
std::size_t loading_asset_count() const noexcept;
|
||||
|
||||
template < typename Asset >
|
||||
typename Asset::load_result load_main_asset(str_view address) const;
|
||||
@@ -49,8 +90,103 @@ namespace e2d
|
||||
|
||||
template < typename Asset, typename Nested = Asset >
|
||||
typename Nested::load_async_result load_asset_async(str_view address) const;
|
||||
private:
|
||||
template < typename Asset >
|
||||
vector<loading_asset_base_iptr>::iterator
|
||||
find_loading_asset_iter_(str_hash address) const noexcept;
|
||||
|
||||
template < typename Asset >
|
||||
typename loading_asset<Asset>::ptr
|
||||
find_loading_asset_(str_hash address) const noexcept;
|
||||
|
||||
template < typename Asset >
|
||||
void remove_loading_asset_(str_hash address) const noexcept;
|
||||
|
||||
void cancel_all_loading_assets_() noexcept;
|
||||
private:
|
||||
url root_;
|
||||
deferrer& deferrer_;
|
||||
std::atomic<bool> cancelled_{false};
|
||||
private:
|
||||
mutable asset_cache cache_;
|
||||
mutable std::recursive_mutex mutex_;
|
||||
mutable vector<loading_asset_base_iptr> loading_assets_;
|
||||
};
|
||||
|
||||
//
|
||||
// asset_group
|
||||
//
|
||||
|
||||
class asset_group {
|
||||
public:
|
||||
asset_group() = default;
|
||||
~asset_group() noexcept = default;
|
||||
|
||||
template < typename Iter >
|
||||
asset_group& add_assets(Iter first, Iter last);
|
||||
|
||||
template < typename Container >
|
||||
asset_group& add_assets(Container&& container);
|
||||
|
||||
asset_group& add_asset(str_view address, const asset_ptr& asset);
|
||||
|
||||
template < typename Asset, typename Nested = Asset >
|
||||
typename Nested::load_result find_asset(str_view address) const;
|
||||
private:
|
||||
vector<std::pair<str, asset_ptr>> assets_;
|
||||
};
|
||||
|
||||
//
|
||||
// asset_dependency_base
|
||||
//
|
||||
|
||||
class asset_dependency_base;
|
||||
using asset_dependency_base_iptr = intrusive_ptr<asset_dependency_base>;
|
||||
|
||||
class asset_dependency_base
|
||||
: private noncopyable
|
||||
, public ref_counter<asset_dependency_base> {
|
||||
public:
|
||||
asset_dependency_base() = default;
|
||||
virtual ~asset_dependency_base() noexcept = default;
|
||||
|
||||
virtual const str& main_address() const noexcept = 0;
|
||||
virtual stdex::promise<asset_ptr> load_async(const library& library) = 0;
|
||||
};
|
||||
|
||||
//
|
||||
// asset_dependency
|
||||
//
|
||||
|
||||
template < typename Asset >
|
||||
class asset_dependency : public asset_dependency_base {
|
||||
public:
|
||||
using asset_type = Asset;
|
||||
using load_result = typename Asset::load_result;
|
||||
public:
|
||||
asset_dependency(str_view address);
|
||||
~asset_dependency() noexcept override;
|
||||
|
||||
const str& main_address() const noexcept override;
|
||||
stdex::promise<asset_ptr> load_async(const library& library) override;
|
||||
private:
|
||||
str main_address_;
|
||||
};
|
||||
|
||||
//
|
||||
// asset_dependencies
|
||||
//
|
||||
|
||||
class asset_dependencies final {
|
||||
public:
|
||||
asset_dependencies() = default;
|
||||
~asset_dependencies() noexcept = default;
|
||||
|
||||
template < typename Asset >
|
||||
asset_dependencies& add_dependency(str_view address);
|
||||
stdex::promise<asset_group> load_async(const library& library);
|
||||
private:
|
||||
vector<asset_dependency_base_iptr> dependencies_;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -13,74 +13,277 @@
|
||||
|
||||
namespace e2d
|
||||
{
|
||||
//
|
||||
// loading_asset
|
||||
//
|
||||
|
||||
template < typename Asset >
|
||||
loading_asset<Asset>::loading_asset(str_hash address, promise_type promise)
|
||||
: address_(address)
|
||||
, promise_(std::move(promise)) {}
|
||||
|
||||
template < typename Asset >
|
||||
void loading_asset<Asset>::cancel() noexcept {
|
||||
promise_.reject(library_cancelled_exception());
|
||||
}
|
||||
|
||||
template < typename Asset >
|
||||
str_hash loading_asset<Asset>::address() const noexcept {
|
||||
return address_;
|
||||
}
|
||||
|
||||
template < typename Asset >
|
||||
const typename loading_asset<Asset>::promise_type& loading_asset<Asset>::promise() const noexcept {
|
||||
return promise_;
|
||||
}
|
||||
|
||||
//
|
||||
// library
|
||||
//
|
||||
|
||||
inline library::library(const url& root, deferrer& deferrer)
|
||||
: root_(root)
|
||||
, deferrer_(deferrer) {}
|
||||
|
||||
inline library::~library() noexcept {
|
||||
std::unique_lock<std::recursive_mutex> lock(mutex_);
|
||||
cancelled_.store(true);
|
||||
cancel_all_loading_assets_();
|
||||
}
|
||||
|
||||
inline const url& library::root() const noexcept {
|
||||
return root_;
|
||||
}
|
||||
|
||||
inline const asset_cache& library::cache() const noexcept {
|
||||
return cache_;
|
||||
}
|
||||
|
||||
inline std::size_t library::unload_unused_assets() noexcept {
|
||||
return cache_.unload_unused_assets();
|
||||
}
|
||||
|
||||
inline std::size_t library::loading_asset_count() const noexcept {
|
||||
std::lock_guard<std::recursive_mutex> guard(mutex_);
|
||||
return loading_assets_.size();
|
||||
}
|
||||
|
||||
template < typename Asset >
|
||||
typename Asset::load_result library::load_main_asset(str_view address) const {
|
||||
auto p = load_main_asset_async<Asset>(address);
|
||||
|
||||
if ( modules::is_initialized<deferrer>() ) {
|
||||
the<deferrer>().active_safe_wait_promise(p);
|
||||
}
|
||||
|
||||
deferrer_.active_safe_wait_promise(p);
|
||||
return p.get_or_default(nullptr);
|
||||
}
|
||||
|
||||
template < typename Asset >
|
||||
typename Asset::load_async_result library::load_main_asset_async(str_view address) const {
|
||||
const auto main_address = address::parent(address);
|
||||
const auto main_address_hash = make_hash(main_address);
|
||||
|
||||
if ( !modules::is_initialized<asset_cache<Asset>>() ) {
|
||||
return Asset::load_async(*this, main_address);
|
||||
if ( cancelled_ ) {
|
||||
return stdex::make_rejected_promise<typename Asset::load_result>(library_cancelled_exception());
|
||||
}
|
||||
|
||||
auto& cache = the<asset_cache<Asset>>();
|
||||
if ( auto cached_asset = cache.find(main_address_hash) ) {
|
||||
const str main_address = address::parent(address);
|
||||
const str_hash main_address_hash = make_hash(main_address);
|
||||
|
||||
std::lock_guard<std::recursive_mutex> guard(mutex_);
|
||||
|
||||
if ( auto cached_asset = cache_.find<Asset>(main_address_hash) ) {
|
||||
return stdex::make_resolved_promise(std::move(cached_asset));
|
||||
}
|
||||
|
||||
return Asset::load_async(*this, main_address)
|
||||
.then([
|
||||
&cache,
|
||||
main_address_hash
|
||||
](const typename Asset::load_result& new_asset){
|
||||
cache.store(main_address_hash, new_asset);
|
||||
return new_asset;
|
||||
});
|
||||
if ( auto asset = find_loading_asset_<Asset>(main_address_hash) ) {
|
||||
return asset->promise();
|
||||
}
|
||||
|
||||
auto p = Asset::load_async(*this, main_address)
|
||||
.then([
|
||||
this,
|
||||
main_address_hash
|
||||
](const typename Asset::load_result& new_asset){
|
||||
std::lock_guard<std::recursive_mutex> guard(mutex_);
|
||||
cache_.store<Asset>(main_address_hash, new_asset);
|
||||
remove_loading_asset_<Asset>(main_address_hash);
|
||||
return new_asset;
|
||||
}).except([
|
||||
this,
|
||||
main_address_hash
|
||||
](std::exception_ptr e) -> typename Asset::load_result {
|
||||
std::lock_guard<std::recursive_mutex> guard(mutex_);
|
||||
remove_loading_asset_<Asset>(main_address_hash);
|
||||
std::rethrow_exception(e);
|
||||
});
|
||||
|
||||
loading_assets_.push_back(new loading_asset<Asset>(address, p));
|
||||
return p;
|
||||
}
|
||||
|
||||
template < typename Asset, typename Nested >
|
||||
typename Nested::load_result library::load_asset(str_view address) const {
|
||||
auto p = load_asset_async<Asset, Nested>(address);
|
||||
|
||||
if ( modules::is_initialized<deferrer>() ) {
|
||||
the<deferrer>().active_safe_wait_promise(p);
|
||||
}
|
||||
|
||||
deferrer_.active_safe_wait_promise(p);
|
||||
return p.get_or_default(nullptr);
|
||||
}
|
||||
|
||||
template < typename Asset, typename Nested >
|
||||
typename Nested::load_async_result library::load_asset_async(str_view address) const {
|
||||
return load_main_asset_async<Asset>(address::parent(address))
|
||||
return load_main_asset_async<Asset>(address)
|
||||
.then([
|
||||
address = str(address)
|
||||
nested_address = address::nested(address)
|
||||
](const typename Asset::load_result& main_asset){
|
||||
asset_ptr nested_asset = main_asset;
|
||||
str nested_address = address::nested(address);
|
||||
|
||||
while ( nested_asset && !nested_address.empty() ) {
|
||||
nested_asset = nested_asset->find_nested_asset(address::parent(nested_address));
|
||||
nested_address = address::nested(nested_address);
|
||||
typename Nested::load_result nested_asset = nested_address.empty()
|
||||
? dynamic_pointer_cast<Nested>(main_asset)
|
||||
: main_asset->template find_nested_asset<Nested>(nested_address);
|
||||
if ( nested_asset ) {
|
||||
return nested_asset;
|
||||
}
|
||||
|
||||
using nested_asset_type = typename Nested::asset_type;
|
||||
if ( auto result = dynamic_pointer_cast<nested_asset_type>(nested_asset) ) {
|
||||
return result;
|
||||
}
|
||||
|
||||
throw asset_loading_exception();
|
||||
});
|
||||
}
|
||||
|
||||
template < typename Asset >
|
||||
vector<loading_asset_base_iptr>::iterator
|
||||
library::find_loading_asset_iter_(str_hash address) const noexcept {
|
||||
return std::find_if(
|
||||
loading_assets_.begin(), loading_assets_.end(),
|
||||
[address](const loading_asset_base_iptr& asset) noexcept {
|
||||
return asset->address() == address
|
||||
&& dynamic_pointer_cast<loading_asset<Asset>>(asset);
|
||||
});
|
||||
}
|
||||
|
||||
template < typename Asset >
|
||||
typename loading_asset<Asset>::ptr
|
||||
library::find_loading_asset_(str_hash address) const noexcept {
|
||||
auto iter = find_loading_asset_iter_<Asset>(address);
|
||||
return iter != loading_assets_.end()
|
||||
? static_pointer_cast<loading_asset<Asset>>(*iter)
|
||||
: nullptr;
|
||||
}
|
||||
|
||||
template < typename Asset >
|
||||
void library::remove_loading_asset_(str_hash address) const noexcept {
|
||||
auto iter = find_loading_asset_iter_<Asset>(address);
|
||||
if ( iter != loading_assets_.end() ) {
|
||||
loading_assets_.erase(iter);
|
||||
}
|
||||
}
|
||||
|
||||
inline void library::cancel_all_loading_assets_() noexcept {
|
||||
for ( const auto& asset : loading_assets_ ) {
|
||||
asset->cancel();
|
||||
}
|
||||
loading_assets_.clear();
|
||||
}
|
||||
|
||||
//
|
||||
// asset_group
|
||||
//
|
||||
|
||||
template < typename Iter >
|
||||
asset_group& asset_group::add_assets(Iter first, Iter last) {
|
||||
for ( auto iter = first; iter != last; ++iter ) {
|
||||
add_asset(iter->first, iter->second);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
template < typename Container >
|
||||
asset_group& asset_group::add_assets(Container&& container) {
|
||||
return add_assets(std::begin(container), std::end(container));
|
||||
}
|
||||
|
||||
inline asset_group& asset_group::add_asset(str_view address, const asset_ptr& asset) {
|
||||
str main_address = address::parent(address);
|
||||
auto iter = std::upper_bound(
|
||||
assets_.begin(), assets_.end(), main_address,
|
||||
[](const str& l, const auto& r){
|
||||
return l < r.first;
|
||||
});
|
||||
assets_.insert(iter, std::make_pair(std::move(main_address), asset));
|
||||
return *this;
|
||||
}
|
||||
|
||||
template < typename Asset, typename Nested >
|
||||
typename Nested::load_result asset_group::find_asset(str_view address) const {
|
||||
const str main_address = address::parent(address);
|
||||
const str nested_address = address::nested(address);
|
||||
auto iter = std::lower_bound(
|
||||
assets_.begin(), assets_.end(), main_address,
|
||||
[](const auto& l, const str& r) noexcept {
|
||||
return l.first < r;
|
||||
});
|
||||
for ( ; iter != assets_.end() && iter->first == main_address; ++iter ) {
|
||||
asset_ptr main_asset = iter->second;
|
||||
typename Asset::load_result typed_main_asset = dynamic_pointer_cast<Asset>(main_asset);
|
||||
if ( !typed_main_asset ) {
|
||||
continue;
|
||||
}
|
||||
typename Nested::load_result nested_asset = nested_address.empty()
|
||||
? dynamic_pointer_cast<Nested>(typed_main_asset)
|
||||
: typed_main_asset->template find_nested_asset<Nested>(nested_address);
|
||||
if ( nested_asset ) {
|
||||
return nested_asset;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
//
|
||||
// asset_dependency
|
||||
//
|
||||
|
||||
template < typename Asset >
|
||||
asset_dependency<Asset>::asset_dependency(str_view address)
|
||||
: main_address_(address::parent(address)) {}
|
||||
|
||||
template < typename Asset >
|
||||
asset_dependency<Asset>::~asset_dependency() noexcept = default;
|
||||
|
||||
template < typename Asset >
|
||||
const str& asset_dependency<Asset>::main_address() const noexcept {
|
||||
return main_address_;
|
||||
}
|
||||
|
||||
template < typename Asset >
|
||||
stdex::promise<asset_ptr> asset_dependency<Asset>::load_async(const library& library) {
|
||||
return library.load_main_asset_async<Asset>(main_address())
|
||||
.then([](const typename Asset::load_result& main_asset){
|
||||
return asset_ptr(main_asset);
|
||||
});
|
||||
}
|
||||
|
||||
//
|
||||
// asset_dependencies
|
||||
//
|
||||
|
||||
template < typename Asset >
|
||||
asset_dependencies& asset_dependencies::add_dependency(str_view address) {
|
||||
asset_dependency_base_iptr dep(new asset_dependency<Asset>(address));
|
||||
auto iter = std::upper_bound(
|
||||
dependencies_.begin(), dependencies_.end(), dep->main_address(),
|
||||
[](const str& l, const auto& r){
|
||||
return l < r->main_address();
|
||||
});
|
||||
dependencies_.insert(iter, std::move(dep));
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline stdex::promise<asset_group> asset_dependencies::load_async(const library& library) {
|
||||
vector<stdex::promise<std::pair<str, asset_ptr>>> promises;
|
||||
promises.reserve(dependencies_.size());
|
||||
std::transform(
|
||||
dependencies_.begin(), dependencies_.end(), std::back_inserter(promises),
|
||||
[&library](const asset_dependency_base_iptr& dep){
|
||||
return dep->load_async(library)
|
||||
.then([main_address = dep->main_address()](const asset_ptr& asset){
|
||||
return std::make_pair(main_address, asset);
|
||||
});
|
||||
});
|
||||
return stdex::make_all_promise(std::move(promises))
|
||||
.then([](const vector<std::pair<str, asset_ptr>>& results){
|
||||
return asset_group()
|
||||
.add_assets(results.begin(), results.end());
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -39,13 +39,13 @@ namespace e2d
|
||||
|
||||
namespace e2d
|
||||
{
|
||||
using str = basic_string<char>;
|
||||
using wstr = basic_string<wchar_t>;
|
||||
using str = basic_string<char>;
|
||||
using wstr = basic_string<wchar_t>;
|
||||
using str16 = basic_string<char16_t>;
|
||||
using str32 = basic_string<char32_t>;
|
||||
|
||||
using str_view = basic_string_view<char>;
|
||||
using wstr_view = basic_string_view<wchar_t>;
|
||||
using str_view = basic_string_view<char>;
|
||||
using wstr_view = basic_string_view<wchar_t>;
|
||||
using str16_view = basic_string_view<char16_t>;
|
||||
using str32_view = basic_string_view<char32_t>;
|
||||
|
||||
@@ -147,4 +147,36 @@ namespace e2d { namespace utils
|
||||
constexpr std::underlying_type_t<E> enum_to_underlying(E e) noexcept {
|
||||
return static_cast<std::underlying_type_t<E>>(e);
|
||||
}
|
||||
|
||||
//
|
||||
// type_family
|
||||
//
|
||||
|
||||
using type_family_id = u32;
|
||||
|
||||
namespace impl
|
||||
{
|
||||
template < typename Void = void >
|
||||
class type_family_base {
|
||||
static_assert(
|
||||
std::is_void<Void>::value &&
|
||||
std::is_unsigned<type_family_id>::value,
|
||||
"unexpected internal error");
|
||||
protected:
|
||||
static type_family_id last_id_;
|
||||
};
|
||||
|
||||
template < typename Void >
|
||||
type_family_id type_family_base<Void>::last_id_ = 0u;
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
class type_family final : public impl::type_family_base<> {
|
||||
public:
|
||||
static type_family_id id() noexcept {
|
||||
static type_family_id self_id = ++last_id_;
|
||||
assert(self_id > 0u && "type_family_id overflow");
|
||||
return self_id;
|
||||
}
|
||||
};
|
||||
}}
|
||||
|
||||
15
scripts/pvs_analyze.sh
Executable file
15
scripts/pvs_analyze.sh
Executable file
@@ -0,0 +1,15 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
BUILD_DIR=`dirname "$BASH_SOURCE"`/../build
|
||||
mkdir -p $BUILD_DIR/pvs_analyze
|
||||
cd $BUILD_DIR/pvs_analyze
|
||||
rm -rf pvs_report
|
||||
cmake -DCMAKE_EXPORT_COMPILE_COMMANDS=On ../..
|
||||
pvs-studio-analyzer analyze\
|
||||
-e ../../untests\
|
||||
-e ../../modules\
|
||||
-e ../../sources/3rdparty\
|
||||
-o pvs_report.log\
|
||||
-j8
|
||||
plog-converter -a GA:1,2 -t fullhtml -o pvs_report pvs_report.log
|
||||
open pvs_report/index.html
|
||||
@@ -1,49 +0,0 @@
|
||||
/*******************************************************************************
|
||||
* This file is part of the "Enduro2D"
|
||||
* For conditions of distribution and use, see copyright notice in LICENSE.md
|
||||
* Copyright (C) 2018-2019, by Matvey Cherevko (blackmatov@gmail.com)
|
||||
******************************************************************************/
|
||||
|
||||
#include <enduro2d/high/asset.hpp>
|
||||
|
||||
namespace e2d
|
||||
{
|
||||
//
|
||||
// asset
|
||||
//
|
||||
|
||||
asset::asset() = default;
|
||||
asset::~asset() noexcept = default;
|
||||
|
||||
//
|
||||
// asset_cache_base
|
||||
//
|
||||
|
||||
std::mutex asset_cache_base::mutex_;
|
||||
hash_set<asset_cache_base*> asset_cache_base::caches_;
|
||||
|
||||
asset_cache_base::asset_cache_base() {
|
||||
std::lock_guard<std::mutex> guard(mutex_);
|
||||
caches_.insert(this);
|
||||
}
|
||||
|
||||
asset_cache_base::~asset_cache_base() noexcept {
|
||||
std::lock_guard<std::mutex> guard(mutex_);
|
||||
caches_.erase(this);
|
||||
}
|
||||
|
||||
std::size_t asset_cache_base::unload_all_unused_assets() noexcept {
|
||||
std::lock_guard<std::mutex> guard(mutex_);
|
||||
return std::accumulate(caches_.begin(), caches_.end(), std::size_t(0),
|
||||
[](std::size_t acc, asset_cache_base* cache){
|
||||
return acc + cache->unload_self_unused_assets();
|
||||
});
|
||||
}
|
||||
|
||||
//
|
||||
// asset_factory
|
||||
//
|
||||
|
||||
asset_factory::asset_factory() = default;
|
||||
asset_factory::~asset_factory() noexcept = default;
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
/*******************************************************************************
|
||||
* This file is part of the "Enduro2D"
|
||||
* For conditions of distribution and use, see copyright notice in LICENSE.md
|
||||
* Copyright (C) 2018-2019, by Matvey Cherevko (blackmatov@gmail.com)
|
||||
******************************************************************************/
|
||||
|
||||
#include <enduro2d/high/library.hpp>
|
||||
|
||||
namespace e2d
|
||||
{
|
||||
library::library(const url& root)
|
||||
: root_(root) {}
|
||||
|
||||
library::~library() noexcept = default;
|
||||
|
||||
const url& library::root() const noexcept {
|
||||
return root_;
|
||||
}
|
||||
|
||||
std::size_t library::unload_unused_assets() noexcept {
|
||||
return asset_cache_base::unload_all_unused_assets();
|
||||
}
|
||||
}
|
||||
@@ -9,20 +9,6 @@
|
||||
#include <enduro2d/high/world.hpp>
|
||||
#include <enduro2d/high/library.hpp>
|
||||
|
||||
#include <enduro2d/high/assets/atlas_asset.hpp>
|
||||
#include <enduro2d/high/assets/binary_asset.hpp>
|
||||
#include <enduro2d/high/assets/flipbook_asset.hpp>
|
||||
#include <enduro2d/high/assets/image_asset.hpp>
|
||||
#include <enduro2d/high/assets/material_asset.hpp>
|
||||
#include <enduro2d/high/assets/mesh_asset.hpp>
|
||||
#include <enduro2d/high/assets/model_asset.hpp>
|
||||
#include <enduro2d/high/assets/prefab_asset.hpp>
|
||||
#include <enduro2d/high/assets/shader_asset.hpp>
|
||||
#include <enduro2d/high/assets/shape_asset.hpp>
|
||||
#include <enduro2d/high/assets/sprite_asset.hpp>
|
||||
#include <enduro2d/high/assets/text_asset.hpp>
|
||||
#include <enduro2d/high/assets/texture_asset.hpp>
|
||||
|
||||
#include <enduro2d/high/systems/flipbook_system.hpp>
|
||||
#include <enduro2d/high/systems/render_system.hpp>
|
||||
|
||||
@@ -129,53 +115,12 @@ namespace e2d
|
||||
|
||||
starter::starter(int argc, char *argv[], const parameters& params) {
|
||||
safe_module_initialize<engine>(argc, argv, params.engine_params());
|
||||
safe_module_initialize<library>(params.library_root());
|
||||
safe_module_initialize<asset_cache<atlas_asset>>(the<library>());
|
||||
safe_module_initialize<asset_cache<binary_asset>>(the<library>());
|
||||
safe_module_initialize<asset_cache<flipbook_asset>>(the<library>());
|
||||
safe_module_initialize<asset_cache<image_asset>>(the<library>());
|
||||
safe_module_initialize<asset_cache<material_asset>>(the<library>());
|
||||
safe_module_initialize<asset_cache<mesh_asset>>(the<library>());
|
||||
safe_module_initialize<asset_cache<model_asset>>(the<library>());
|
||||
safe_module_initialize<asset_cache<prefab_asset>>(the<library>());
|
||||
safe_module_initialize<asset_cache<shader_asset>>(the<library>());
|
||||
safe_module_initialize<asset_cache<shape_asset>>(the<library>());
|
||||
safe_module_initialize<asset_cache<sprite_asset>>(the<library>());
|
||||
safe_module_initialize<asset_cache<text_asset>>(the<library>());
|
||||
safe_module_initialize<asset_cache<texture_asset>>(the<library>());
|
||||
safe_module_initialize<asset_factory>()
|
||||
.register_asset<atlas_asset>("atlas")
|
||||
.register_asset<binary_asset>("binary")
|
||||
.register_asset<flipbook_asset>("flipbook")
|
||||
.register_asset<image_asset>("image")
|
||||
.register_asset<material_asset>("material")
|
||||
.register_asset<mesh_asset>("mesh")
|
||||
.register_asset<model_asset>("model")
|
||||
.register_asset<prefab_asset>("prefab")
|
||||
.register_asset<shader_asset>("shader")
|
||||
.register_asset<shape_asset>("shape")
|
||||
.register_asset<sprite_asset>("sprite")
|
||||
.register_asset<text_asset>("text")
|
||||
.register_asset<texture_asset>("texture");
|
||||
safe_module_initialize<library>(params.library_root(), the<deferrer>());
|
||||
safe_module_initialize<world>();
|
||||
}
|
||||
|
||||
starter::~starter() noexcept {
|
||||
modules::shutdown<world>();
|
||||
modules::shutdown<asset_factory>();
|
||||
modules::shutdown<asset_cache<texture_asset>>();
|
||||
modules::shutdown<asset_cache<text_asset>>();
|
||||
modules::shutdown<asset_cache<sprite_asset>>();
|
||||
modules::shutdown<asset_cache<shape_asset>>();
|
||||
modules::shutdown<asset_cache<shader_asset>>();
|
||||
modules::shutdown<asset_cache<prefab_asset>>();
|
||||
modules::shutdown<asset_cache<model_asset>>();
|
||||
modules::shutdown<asset_cache<mesh_asset>>();
|
||||
modules::shutdown<asset_cache<material_asset>>();
|
||||
modules::shutdown<asset_cache<image_asset>>();
|
||||
modules::shutdown<asset_cache<flipbook_asset>>();
|
||||
modules::shutdown<asset_cache<binary_asset>>();
|
||||
modules::shutdown<asset_cache<atlas_asset>>();
|
||||
modules::shutdown<library>();
|
||||
modules::shutdown<engine>();
|
||||
}
|
||||
|
||||
@@ -44,36 +44,43 @@ namespace
|
||||
};
|
||||
}
|
||||
|
||||
TEST_CASE("asset"){
|
||||
TEST_CASE("asset") {
|
||||
safe_starter_initializer initializer;
|
||||
library& l = the<library>();
|
||||
{
|
||||
REQUIRE_FALSE(l.load_asset<fake_asset>("none"));
|
||||
SECTION("nested_assets") {
|
||||
{
|
||||
REQUIRE_FALSE(l.load_asset<fake_asset>("none"));
|
||||
|
||||
auto fa = l.load_asset<fake_asset>("42");
|
||||
REQUIRE(fa);
|
||||
REQUIRE(fa->content() == 42);
|
||||
auto fa = l.load_asset<fake_asset>("42");
|
||||
REQUIRE(fa);
|
||||
REQUIRE(fa->content() == 42);
|
||||
|
||||
REQUIRE_FALSE(fa->find_nested_asset("none"));
|
||||
REQUIRE(fa->find_nested_asset("21"));
|
||||
REQUIRE_FALSE(fa->find_nested_asset<binary_asset>("21"));
|
||||
REQUIRE(fa->find_nested_asset<fake_nested_asset>("21"));
|
||||
REQUIRE(fa->find_nested_asset<fake_nested_asset>("21")->content() == 21);
|
||||
REQUIRE(fa->find_nested_asset<fake_nested_asset>("84")->content() == 84);
|
||||
}
|
||||
{
|
||||
REQUIRE(l.load_asset<fake_asset, fake_nested_asset>("42:/21"));
|
||||
REQUIRE(l.load_asset<fake_asset, fake_nested_asset>("42:/21")->content() == 21);
|
||||
REQUIRE_FALSE(fa->find_nested_asset("none"));
|
||||
REQUIRE(fa->find_nested_asset("21"));
|
||||
REQUIRE(fa->find_nested_asset("21:/2"));
|
||||
REQUIRE_FALSE(fa->find_nested_asset<binary_asset>("21"));
|
||||
REQUIRE_FALSE(fa->find_nested_asset<binary_asset>("21:/2"));
|
||||
REQUIRE(fa->find_nested_asset<fake_nested_asset>("21"));
|
||||
REQUIRE(fa->find_nested_asset<fake_nested_asset>("21:/2"));
|
||||
REQUIRE(fa->find_nested_asset<fake_nested_asset>("21")->content() == 21);
|
||||
REQUIRE(fa->find_nested_asset<fake_nested_asset>("21:/2")->content() == 2);
|
||||
REQUIRE(fa->find_nested_asset<fake_nested_asset>("84")->content() == 84);
|
||||
REQUIRE(fa->find_nested_asset<fake_nested_asset>("84:/8")->content() == 8);
|
||||
}
|
||||
{
|
||||
REQUIRE(l.load_asset<fake_asset, fake_nested_asset>("42:/21"));
|
||||
REQUIRE(l.load_asset<fake_asset, fake_nested_asset>("42:/21")->content() == 21);
|
||||
|
||||
REQUIRE_FALSE(l.load_asset<fake_asset, binary_asset>("42:/21"));
|
||||
REQUIRE_FALSE(l.load_asset<fake_asset, fake_nested_asset>("42:/none"));
|
||||
REQUIRE_FALSE(l.load_asset<fake_asset, fake_nested_asset>("42:/none:/21"));
|
||||
REQUIRE_FALSE(l.load_asset<fake_asset, binary_asset>("42:/21"));
|
||||
REQUIRE_FALSE(l.load_asset<fake_asset, fake_nested_asset>("42:/none"));
|
||||
REQUIRE_FALSE(l.load_asset<fake_asset, fake_nested_asset>("42:/none:/21"));
|
||||
|
||||
REQUIRE(l.load_asset<fake_asset, fake_nested_asset>("42:/21:/2"));
|
||||
REQUIRE(l.load_asset<fake_asset, fake_nested_asset>("42:/21:/2")->content() == 2);
|
||||
REQUIRE(l.load_asset<fake_asset, fake_nested_asset>("42:/21:/2"));
|
||||
REQUIRE(l.load_asset<fake_asset, fake_nested_asset>("42:/21:/2")->content() == 2);
|
||||
|
||||
REQUIRE_FALSE(l.load_asset<fake_asset, binary_asset>("42:/21:/2"));
|
||||
REQUIRE_FALSE(l.load_asset<fake_asset, fake_nested_asset>("42:/21:/none"));
|
||||
REQUIRE_FALSE(l.load_asset<fake_asset, fake_nested_asset>("42:/21:/none:/2"));
|
||||
REQUIRE_FALSE(l.load_asset<fake_asset, binary_asset>("42:/21:/2"));
|
||||
REQUIRE_FALSE(l.load_asset<fake_asset, fake_nested_asset>("42:/21:/none"));
|
||||
REQUIRE_FALSE(l.load_asset<fake_asset, fake_nested_asset>("42:/21:/none:/2"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,6 +27,44 @@ namespace
|
||||
TEST_CASE("library"){
|
||||
safe_starter_initializer initializer;
|
||||
library& l = the<library>();
|
||||
{
|
||||
binary_asset::ptr b1;
|
||||
binary_asset::ptr b2;
|
||||
|
||||
{
|
||||
auto p1 = l.load_asset_async<binary_asset>("binary_asset.bin");
|
||||
auto p2 = l.load_asset_async<binary_asset>("binary_asset.bin");
|
||||
|
||||
the<deferrer>().active_safe_wait_promise(p1);
|
||||
the<deferrer>().active_safe_wait_promise(p2);
|
||||
|
||||
b1 = p1.get();
|
||||
b2 = p2.get();
|
||||
REQUIRE(b1 == b2);
|
||||
}
|
||||
|
||||
b1.reset();
|
||||
b2.reset();
|
||||
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(10));
|
||||
REQUIRE(1u == l.unload_unused_assets());
|
||||
REQUIRE(l.cache().asset_count<binary_asset>() == 0);
|
||||
}
|
||||
{
|
||||
{
|
||||
auto p1 = l.load_asset_async<binary_asset>("binary_asset.bin");
|
||||
REQUIRE(l.loading_asset_count() == 1);
|
||||
the<deferrer>().active_safe_wait_promise(p1);
|
||||
REQUIRE(l.loading_asset_count() == 0);
|
||||
|
||||
auto p2 = l.load_asset_async<binary_asset>("none_asset");
|
||||
REQUIRE(l.loading_asset_count() == 1);
|
||||
the<deferrer>().active_safe_wait_promise(p2);
|
||||
REQUIRE(l.loading_asset_count() == 0);
|
||||
}
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(10));
|
||||
REQUIRE(1u == l.unload_unused_assets());
|
||||
}
|
||||
{
|
||||
auto text_res = l.load_asset<text_asset>("text_asset.txt");
|
||||
REQUIRE(text_res);
|
||||
@@ -36,15 +74,17 @@ TEST_CASE("library"){
|
||||
REQUIRE(text_res_from_cache);
|
||||
REQUIRE(text_res_from_cache.get() == text_res.get());
|
||||
|
||||
REQUIRE(0u == the<asset_cache<text_asset>>().unload_self_unused_assets());
|
||||
REQUIRE(the<asset_cache<text_asset>>().asset_count() == 1);
|
||||
REQUIRE(0u == l.unload_unused_assets());
|
||||
REQUIRE(l.cache().asset_count() == 1);
|
||||
REQUIRE(l.cache().asset_count<text_asset>() == 1);
|
||||
|
||||
text_res.reset();
|
||||
text_res_from_cache.reset();
|
||||
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(10));
|
||||
REQUIRE(1u == the<asset_cache<text_asset>>().unload_self_unused_assets());
|
||||
REQUIRE(the<asset_cache<text_asset>>().asset_count() == 0);
|
||||
REQUIRE(1u == l.unload_unused_assets());
|
||||
REQUIRE(l.cache().asset_count() == 0);
|
||||
REQUIRE(l.cache().asset_count<text_asset>() == 0);
|
||||
}
|
||||
{
|
||||
auto text_res = l.load_asset<text_asset>("text_asset.txt");
|
||||
@@ -56,12 +96,14 @@ TEST_CASE("library"){
|
||||
REQUIRE(binary_res->content() == buffer("world", 5));
|
||||
|
||||
REQUIRE(0u == l.unload_unused_assets());
|
||||
REQUIRE(l.cache().asset_count() == 2);
|
||||
|
||||
text_res.reset();
|
||||
binary_res.reset();
|
||||
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(10));
|
||||
REQUIRE(2u == l.unload_unused_assets());
|
||||
REQUIRE(l.cache().asset_count() == 0);
|
||||
}
|
||||
{
|
||||
auto empty_res = l.load_asset<binary_asset>("empty_asset");
|
||||
@@ -72,19 +114,19 @@ TEST_CASE("library"){
|
||||
REQUIRE(image_res);
|
||||
REQUIRE(!image_res->content().empty());
|
||||
|
||||
REQUIRE(the<asset_cache<image_asset>>().find("image.png"));
|
||||
REQUIRE(the<asset_cache<binary_asset>>().find("image.png"));
|
||||
REQUIRE(l.cache().find<image_asset>("image.png"));
|
||||
REQUIRE(l.cache().find<binary_asset>("image.png"));
|
||||
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(10));
|
||||
the<asset_cache<binary_asset>>().unload_self_unused_assets();
|
||||
REQUIRE(the<asset_cache<image_asset>>().find("image.png"));
|
||||
REQUIRE_FALSE(the<asset_cache<binary_asset>>().find("image.png"));
|
||||
l.unload_unused_assets();
|
||||
REQUIRE(l.cache().find<image_asset>("image.png"));
|
||||
REQUIRE_FALSE(l.cache().find<binary_asset>("image.png"));
|
||||
|
||||
image_res.reset();
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(10));
|
||||
the<asset_cache<image_asset>>().unload_self_unused_assets();
|
||||
REQUIRE_FALSE(the<asset_cache<image_asset>>().find("image.png"));
|
||||
REQUIRE_FALSE(the<asset_cache<binary_asset>>().find("image.png"));
|
||||
l.unload_unused_assets();
|
||||
REQUIRE_FALSE(l.cache().find<image_asset>("image.png"));
|
||||
REQUIRE_FALSE(l.cache().find<binary_asset>("image.png"));
|
||||
}
|
||||
{
|
||||
if ( modules::is_initialized<render>() ) {
|
||||
@@ -284,3 +326,39 @@ TEST_CASE("library"){
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("asset_dependencies") {
|
||||
safe_starter_initializer initializer;
|
||||
library& l = the<library>();
|
||||
{
|
||||
auto ad = asset_dependencies()
|
||||
.add_dependency<text_asset>("text_asset.txt")
|
||||
.add_dependency<binary_asset>("binary_asset.bin");
|
||||
auto g1_p = ad.load_async(l);
|
||||
the<deferrer>().active_safe_wait_promise(g1_p);
|
||||
asset_group g1 = g1_p.get();
|
||||
REQUIRE(g1.find_asset<text_asset>("text_asset.txt"));
|
||||
REQUIRE(g1.find_asset<binary_asset>("binary_asset.bin"));
|
||||
|
||||
ad.add_dependency<text_asset>("none_asset");
|
||||
auto g2_p = ad.load_async(l);
|
||||
the<deferrer>().active_safe_wait_promise(g2_p);
|
||||
}
|
||||
{
|
||||
if ( modules::is_initialized<render>() ) {
|
||||
auto ad = asset_dependencies()
|
||||
.add_dependency<atlas_asset>("atlas.json:/sprite");
|
||||
auto g1_p = ad.load_async(l);
|
||||
the<deferrer>().active_safe_wait_promise(g1_p);
|
||||
asset_group g1 = g1_p.get();
|
||||
REQUIRE(g1.find_asset<atlas_asset>("atlas.json")
|
||||
== l.load_asset<atlas_asset>("atlas.json"));
|
||||
REQUIRE(g1.find_asset<atlas_asset, sprite_asset>("atlas.json:/sprite")
|
||||
== l.load_asset<atlas_asset, sprite_asset>("atlas.json:/sprite"));
|
||||
|
||||
ad.add_dependency<sprite_asset>("atlas.json:/sprite");
|
||||
auto g2_p = ad.load_async(l);
|
||||
the<deferrer>().active_safe_wait_promise(g2_p);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -49,4 +49,11 @@ TEST_CASE("utils") {
|
||||
42u, str1, str1 + std::strlen(str1)
|
||||
) == utils::sdbm_hash(42u, str2));
|
||||
}
|
||||
{
|
||||
utils::type_family_id id1 = utils::type_family<str16>::id();
|
||||
utils::type_family_id id2 = utils::type_family<str32>::id();
|
||||
REQUIRE(id1 != id2);
|
||||
REQUIRE(id1 == utils::type_family<str16>::id());
|
||||
REQUIRE(id2 == utils::type_family<str32>::id());
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user