# Tutorial for Asynchronous Asset-Loading

# Asynchronous Asset-Loading

#### <a class="anchor" id="bkmrk-"></a>Description

This tutorial describes Asynchronous Asset-Loading and provides short examples on how to load a bitmap.

#### <a class="anchor" id="bkmrk--0"></a>Asynchronous Asset-Loading

Asset Loading, especially reading from the asset repositories, can be a time consuming task, which blocks the CPU from further processing. This can even slow down rendering in certain cases. To improve this, asset loading requests can now be submitted as asynchronous jobs. These jobs can be done either in parallel on a separate thread, or interleaved with the rendering in smaller chunks. Whenever an asset is available, the main thread can retrieve it and add it to the render loop.

#### <a class="anchor" id="bkmrk--1"></a>How to activate this in the application

For a [Courier](http://dev.doc.cgistudio.at/APILINK/namespace_courier.html) based application, the AsyncLoadReqMsg message can be used to load Views. For a [Candera](http://dev.doc.cgistudio.at/APILINK/namespace_candera.html "[DataBinding_RefTypeSample]") based application, Async version of the asset loader methods can be used (see AsyncAssetProviderProxy and new ContentLoader methods).

#### <a class="anchor" id="bkmrk--2"></a>Number of threads for asynchronous asset loading

To load the assets asynchronously in one single thread, the interface "AsyncAssetProviderProxy" can be used. It is available from any AssetProvider implementation via the AssetProvider::AsyncProxy() method. Using a second thread for async loading can be achieved by checking the CANDERA\_ASSETLOADER\_WORKER\_THREAD\_ENABLED in Cmake. AsyncRequests will be dispatched on the worker thread as soon as possible. For multithreaded async asset loading, the CMake flag CANDERA\_ASSETLOADER\_WORKER\_THREAD\_ENABLED specifies if the asynchronous asset load requests are handled on a dedicated thread or on the caller one.

#### <a class="anchor" id="bkmrk--3"></a>Upload

Upload can be done asynchronously too, as ContentLoader::BuildSceneContextAsync can also upload to VRAM (depending on a parameter value). In this case, the single threaded variant must be used.

#### <a class="anchor" id="bkmrk--4"></a>Examples

In the AsyncAssetProviderProxy, each Get\* (GetScene) function schedules a Get\* (GetSceneById) call on the AssetProvider that created the Proxy. In the case that CANDERA\_ASSETLOADER\_WROKER\_THREAD\_ENABLED flag is enabled in CMAKE, the AssetProvider::Get\* call will be dispatched on a separate thread and the result will be available as soon as the worker thread completes the dispatch. In the case that the above mentioned CMake option is disabled, one or more calls to DispatchNext() need to be performed on the current thread to assure that the request is dispatched. It is advised to call the DispatchNext() routine periodically during the Update part of the render loop of the application to ensure all asynchronous asset load requests are dispatched in a controlled and limited time. One option to call DispatchNext would be to introduce it in the LateUpdate part of the UpdateSystem provided by [Candera](http://dev.doc.cgistudio.at/APILINK/namespace_candera.html "[DataBinding_RefTypeSample]").

```
       AssetProvider* assetProvider = ContentLoader::GetInstance().GetAssetProvider();
       if (assetProvider != 0) {
         UpdateSystem* updateSystem = EntityComponentSystem::EntitySystem::Get<UpdateSystem>();
         if (updateSystem != 0) {
           UpdateSystem::Handle updateHandle = updateSystem->CreateComponent();
           UpdateSystem::Delegate delegate = UpdateSystem::Delegate::Update<AsyncAssetProviderProxy, &AsyncAssetProviderProxy::DispatchNext>();
           updateSystem->SetComponentLateUpdateDelegate(updateHandle, delegate);
           updateSystem->AttachComponent(updateHandle, &assetProvider->AsyncProxy());
         }
       }
```

Samples to retrieve a Bitmap Asynchronously:

<div class="contents" id="bkmrk-if-candera_assetload"><div class="textblock">- If CANDERA\_ASSETLOADER\_WORKER\_THREAD\_ENABLED is enabled (processing is done on a separate thread)
    
    ```
    BitmapAsyncRequestSharedPointer request = assetProvider->AsyncProxy()->GetBitmap();
      <a class="code" href="http://dev.doc.cgistudio.at/APILINK/class_candera_1_1_asset_provider.html" title="Abstract class providing methods for retrieving objects.">Candera::AssetProvider</a>* provider;
      <a class="code" href="http://dev.doc.cgistudio.at/APILINK/class_candera_1_1_async_asset_provider_proxy.html">Candera::AsyncAssetProviderProxy</a>& proxy = provider-><a class="code" href="http://dev.doc.cgistudio.at/APILINK/class_candera_1_1_asset_provider.html#a9c5264e99d06a295542bf31809aa737b">AsyncProxy</a>();
      <a class="code" href="http://dev.doc.cgistudio.at/APILINK/class_feat_std_1_1_memory_management_1_1_shared_pointer.html" title="An intrusive reference-counting smart pointer. If you want your class to be managed by SharedPointer ...">Candera::AsyncAssetProviderProxy::BitmapAsyncRequestSharedPointer</a> asyncRequest = proxy.<a class="code" href="http://dev.doc.cgistudio.at/APILINK/class_candera_1_1_async_asset_provider_proxy.html#a25d3620ee6fc846d9882a216cd5079a1">GetBitmap</a>(0x123);
      //do other stuff
      Candera::Bitmap::SharedPointer bitmap;
      if (asyncRequest->IsCompleted()) {
          //bitmap was asynchronously loaded
          bitmap = asyncRequest->GetResult();
    }
    ```
- If CANDERA\_ASSETLOADER\_WORKER\_THREAD\_ENABLED is disabled (processing is done later on the same thread, by calling DispatchNext) ```
    BitmapAsyncRequestSharedPointer request = assetProvider->AsyncProxy()->GetBitmap();
      <a class="code" href="http://dev.doc.cgistudio.at/APILINK/class_candera_1_1_asset_provider.html" title="Abstract class providing methods for retrieving objects.">Candera::AssetProvider</a>* provider;
      <a class="code" href="http://dev.doc.cgistudio.at/APILINK/class_candera_1_1_async_asset_provider_proxy.html">Candera::AsyncAssetProviderProxy</a>& proxy = provider-><a class="code" href="http://dev.doc.cgistudio.at/APILINK/class_candera_1_1_asset_provider.html#a9c5264e99d06a295542bf31809aa737b">AsyncProxy</a>();
      <a class="code" href="http://dev.doc.cgistudio.at/APILINK/class_feat_std_1_1_memory_management_1_1_shared_pointer.html" title="An intrusive reference-counting smart pointer. If you want your class to be managed by SharedPointer ...">Candera::AsyncAssetProviderProxy::BitmapAsyncRequestSharedPointer</a> asyncRequest = proxy.<a class="code" href="http://dev.doc.cgistudio.at/APILINK/class_candera_1_1_async_asset_provider_proxy.html#a25d3620ee6fc846d9882a216cd5079a1">GetBitmap</a>(0x123);
      //do other stuff
      proxy.<a class="code" href="http://dev.doc.cgistudio.at/APILINK/class_candera_1_1_async_asset_provider_proxy.html#ac823745938c26082ad68aeccff5e950c">DispatchNext</a>();
      //do other stuff
      Candera::Bitmap::SharedPointer bitmap;
      if (asyncRequest->IsCompleted()) {
          //bitmap was asynchronously loaded
          bitmap = asyncRequest->GetResult();
    }
    ```

</div></div>