Sign in to follow this  
B_old

Handle for asynchronously loaded resources

Recommended Posts

When I load resources (synchronously) I return a Handle<T>. This is a pointer to the real resource & a pointer to a reference counting variable. A copy of the handle is returned if the resource is requested again from another place.
For asynchronous resource loading I considered adding a second layer of indirection inside the handle. The idea is to be able to use many copies of the handle in different places immediately and place the actual resource "under" them once loading has finished. Of course I still had to check for null if I wasn't sure whether the resource has loaded yet.
What do you think of this? Does it seem like a bad idea to always carry around that double level of indirection even for stuff that isn't even asynchronously loaded?

Share this post


Link to post
Share on other sites
It all depends.

If you have tens of thousands of assets in flight in a given gameplay session, with textures and models and shaders and animations and any number of other resources being loaded through this mechanism, then yeah, the double indirection is going to add up and bite you.

If you're writing a Mario clone, it's almost certainly no big deal.

Share this post


Link to post
Share on other sites
[quote name='phantom' timestamp='1318974343' post='4874057']
So don't bother with the double indirection; instead allow your handle class to indicate its ready state and allow the resource loader to patch in the correct pointer later via an atomic operation.
[/quote]
I haven't figured out how to patch in the correct pointer later. How is this possible if I don't know where the different copies of the resource handle are located?

Share this post


Link to post
Share on other sites
When I load a resource, I synchronously construct the resource's header, and return a handle to it immediately. The header contains a "is loaded" flag. The asynchronous load fills in the header in the background ([i]which may involve setting pointers to newly loaded blobs[/i]), and then atomically sets the flag to true.

In practice, this is basically a double-indirection, as you've got a handle to the header, and the header may have a pointer to some other data.
Double-indirections are themselves not a problem -- what is a problem is non-locality. If your double (or tripple, or quadruple) indirections cause you to jump between 3 (or 4, or 5) different memory areas in a completely random pattern, then it's going to lead to bad performance. If your indirections are all fairly local, then it's not a problem.

Share this post


Link to post
Share on other sites
Sorry, I didn't mean to imply that simply having a header will improve locality -- just that double indirection isn't that bad as long as your locality is good.

One tactic that I use for having good locality, is to pre-load the sizes of [i]all [/i]my resources into an array, so that when loading a resource, I can allocate enough space for both the header and any other required allocations before even starting the asynchronous load. In a lot of cases, the header and data areas are in a contiguous allocation.

Another tactic is to store all headers in a pool structure. Usually when performing operations on a resource, you will also be performing similar operations on other resources of the same type. So by storing all the headers of that resource-type together, you improve the locality for cases where you access many different headers in succession.

Share this post


Link to post
Share on other sites
If you decide to use a proxy class which implements the interface, to be able to lazy initialize or asynchronous loading. Then you can add a method which will remove extra layers of indirection, by returning the proxied objects... I've used this once for multithreaded loading of textures asynchronously.

[code]
class texture2d
{
public:
// ...
virtual shared_ptr<texture2d> optimized() const = 0;
};

class asynchronously_loaded_texture2d : public texture2d
{
shared_ptr<texture2d> result;

public:
// ...
shared_ptr<texture2d> optimized() const
{
if (!loaded())
wait_until_loaded();

return result;
}
};
[/code]

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this