library waits for loading assets in destroying now

This commit is contained in:
2019-05-24 06:47:22 +07:00
parent fa5080fd35
commit 408dcd4205
3 changed files with 57 additions and 49 deletions

View File

@@ -32,7 +32,7 @@ namespace e2d
stdex::promise<R> do_in_worker_thread(F&& f, Args&&... args);
template < typename T >
void active_safe_wait_promise(const stdex::promise<T>& promise);
void active_safe_wait_promise(const stdex::promise<T>& promise) noexcept;
private:
stdex::jobber worker_;
stdex::scheduler scheduler_;
@@ -52,7 +52,7 @@ namespace e2d
}
template < typename T >
void deferrer::active_safe_wait_promise(const stdex::promise<T>& promise) {
void deferrer::active_safe_wait_promise(const stdex::promise<T>& promise) noexcept {
const auto zero_us = time::to_chrono(make_microseconds(0));
while ( promise.wait_for(zero_us) == stdex::promise_wait_status::timeout ) {
if ( !is_in_main_thread() || 0 == scheduler_.process_one_task().second ) {

View File

@@ -24,39 +24,37 @@ namespace e2d
}
};
//
// 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 {
class loading_asset;
using loading_asset_iptr = intrusive_ptr<loading_asset>;
class loading_asset
: private noncopyable
, public ref_counter<loading_asset> {
public:
using ptr = intrusive_ptr<loading_asset>;
loading_asset() = default;
virtual ~loading_asset() noexcept = default;
virtual void cancel() noexcept = 0;
virtual str_hash address() const noexcept = 0;
virtual void wait(deferrer& deferrer) const noexcept = 0;
};
template < typename Asset >
class typed_loading_asset : public loading_asset {
public:
using ptr = intrusive_ptr<typed_loading_asset>;
using promise_type = typename Asset::load_async_result;
public:
loading_asset(str_hash address, promise_type promise);
~loading_asset() noexcept override = default;
typed_loading_asset(str_hash address, promise_type promise);
~typed_loading_asset() noexcept override = default;
void cancel() noexcept override;
str_hash address() const noexcept override;
void wait(deferrer& deferrer) const noexcept override;
const promise_type& promise() const noexcept;
private:
@@ -92,17 +90,17 @@ namespace e2d
typename Nested::load_async_result load_asset_async(str_view address) const;
private:
template < typename Asset >
vector<loading_asset_base_iptr>::iterator
vector<loading_asset_iptr>::iterator
find_loading_asset_iter_(str_hash address) const noexcept;
template < typename Asset >
typename loading_asset<Asset>::ptr
typename typed_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;
void wait_all_loading_assets_() noexcept;
private:
url root_;
deferrer& deferrer_;
@@ -110,7 +108,7 @@ namespace e2d
private:
mutable asset_cache cache_;
mutable std::recursive_mutex mutex_;
mutable vector<loading_asset_base_iptr> loading_assets_;
mutable vector<loading_asset_iptr> loading_assets_;
};
//

View File

@@ -18,25 +18,31 @@ namespace e2d
//
template < typename Asset >
loading_asset<Asset>::loading_asset(str_hash address, promise_type promise)
typed_loading_asset<Asset>::typed_loading_asset(str_hash address, promise_type promise)
: address_(address)
, promise_(std::move(promise)) {}
template < typename Asset >
void loading_asset<Asset>::cancel() noexcept {
void typed_loading_asset<Asset>::cancel() noexcept {
promise_.reject(library_cancelled_exception());
}
template < typename Asset >
str_hash loading_asset<Asset>::address() const noexcept {
str_hash typed_loading_asset<Asset>::address() const noexcept {
return address_;
}
template < typename Asset >
const typename loading_asset<Asset>::promise_type& loading_asset<Asset>::promise() const noexcept {
const typename typed_loading_asset<Asset>::promise_type&
typed_loading_asset<Asset>::promise() const noexcept {
return promise_;
}
template < typename Asset >
void typed_loading_asset<Asset>::wait(deferrer& deferrer) const noexcept {
deferrer.active_safe_wait_promise(promise_);
}
//
// library
//
@@ -46,9 +52,8 @@ namespace e2d
, deferrer_(deferrer) {}
inline library::~library() noexcept {
std::lock_guard<std::recursive_mutex> guard(mutex_);
cancelled_.store(true);
cancel_all_loading_assets_();
wait_all_loading_assets_();
}
inline const url& library::root() const noexcept {
@@ -77,15 +82,15 @@ namespace e2d
template < typename Asset >
typename Asset::load_async_result library::load_main_asset_async(str_view address) const {
if ( cancelled_ ) {
return stdex::make_rejected_promise<typename Asset::load_result>(library_cancelled_exception());
}
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 ( cancelled_ ) {
return stdex::make_rejected_promise<typename Asset::load_result>(library_cancelled_exception());
}
if ( auto cached_asset = cache_.find<Asset>(main_address_hash) ) {
return stdex::make_resolved_promise(std::move(cached_asset));
}
@@ -135,7 +140,7 @@ namespace e2d
const auto zero_us = time::to_chrono(make_microseconds(0));
if ( p.wait_for(zero_us) == stdex::promise_wait_status::timeout ) {
loading_assets_.push_back(new loading_asset<Asset>(main_address_hash, p));
loading_assets_.push_back(new typed_loading_asset<Asset>(main_address_hash, p));
}
return p;
@@ -173,22 +178,22 @@ namespace e2d
}
template < typename Asset >
vector<loading_asset_base_iptr>::iterator
vector<loading_asset_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 {
[address](const loading_asset_iptr& asset) noexcept {
return asset->address() == address
&& dynamic_pointer_cast<loading_asset<Asset>>(asset);
&& dynamic_pointer_cast<typed_loading_asset<Asset>>(asset);
});
}
template < typename Asset >
typename loading_asset<Asset>::ptr
typename typed_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)
? static_pointer_cast<typed_loading_asset<Asset>>(*iter)
: nullptr;
}
@@ -200,11 +205,16 @@ namespace e2d
}
}
inline void library::cancel_all_loading_assets_() noexcept {
for ( const auto& asset : loading_assets_ ) {
asset->cancel();
inline void library::wait_all_loading_assets_() noexcept {
while ( true ) {
std::unique_lock<std::recursive_mutex> lock(mutex_);
if ( loading_assets_.empty() ) {
break;
}
const auto loading_asset_copy = loading_assets_.back();
lock.unlock();
loading_asset_copy->wait(deferrer_);
}
loading_assets_.clear();
}
//