realXtend/naali — pull request #707 by jonnenauha (2013-07-26 22:09:26+00:00)
Title: Meshmoon -  Async HttpAssetProvider cache disk write

I cooked this up on my summer holiday for fun, have been thinking for a long time that our cache IO should be made asynchronous. I've actually started this "project" many times, but always after one night of coding abandoned the idea because it would change too much of the AssetAPI internals.

* Cache writes can be performed by the providers, this is the case with HttpAssetProvider. This is where I started my work as it was the lowest hanging fruit. Modifying cache writes out of the main thread in AssetAPI would not be too hard to implement, just another operation and waiting for a signal to continue reporting that the transfer has completed.
* Cache reads are performed by IAsset or if overridden in asset implementations. Texture and Mesh assets already skip reading from disk if async loading is allowed in `LoadFromFile` that AssetAPI calls if the transfers raw data is null. This will happen if HttpAssetProvider gets a 304 Not Modified response, disk source is set but the raw data is not filled.
* This mechanism actually works well for Texture and Mesh (lets Ogre handle an async disk load) but all others asset types go to `IAsset::LoadFromFile` that will block the main thread. Making `IAsset::LoadFromFile` async would require bigger structural changes to AssetAPI: Should return a DiskLoadOperation or something that would have a signal for completion. Currently many places both internally in AssetAPI and outside code expect that the asset is in fact loaded when `LoadFromFile` returns, and they continue to use the asset ptr. Changing the function signature would easily allow us to fix all the places that expect this result and port them, but it would be a breaking change in the API.

Granted nowadays hard drives are very fast, SSDs are getting very common etc. I still believe we should aim to move disk I/O out of the main thread. Certain assets can be very big like .zip bundles (note: this pull request fixed the write and ZipAssetBundle internally threads the disk read), big textures, big mesh files, big audio files (I've seen 90mb wav files in scenes) etc. Doing this I/O in the main thread during the login phase is pretty much ok, but we will soon be moving to asset interest systems and scripts that request/load assets during runtime and then it will affect the user experience as FPS drops.

I'd love to hear from everyone how this code looks to start with and if you have any opinions how we could thread more asset implementation load operation and the generic `IAsset::LoadFromFile`.

Cheers!