Scaleform::GFx::ResourceLib
class ResourceLib : public RefCountBase<ResourceLib, Stat_Default_Mem>;
ResourceLib is a thread-safe library used for sharing resources based on their keys. Different types of resources can exist in the library simultaneously, including both user-created external resources as well as resources created internally by the flash file. If two Loader objects have the same library, they will be able to share resources.
Strong and Weak Libraries
To facilitate automated sharing of resources without reference counting problems the library is separated into a strong and weak library classes, as follows:
- ResourceLib is a strong library, owned by loader.
- ResourceWeakLib is a weak library, owned by ResourceLib and also owned/shared by the movies. ResourceWeakLib can exist without the strong library, but not the other way around.
Any sharable resource loaded into memory always exists in a weak library; however, the weak library does not AddRef to the resource. If the resource is released because its reference count is decremented, it will also update ResourceWeakLib in a thread safe manner. Movie resources will get released if the user releases all of their smart pointer references to the movie instances and definitions. No extra work needs to be done if the developer is content with automated sharing.
If the developer would like the resource to remain alive, they can do so by either keeping a smart pointer to it or 'pinning' it in memory. Pinning a resource creates a smart pointer to it in the strong library; it is achieved by calling Resource::PinResource. Once a resource is pinned it will remain alive and sharable until a strong library itself is released (this normally happens when Loader is destroyed).
Adding Resources to Library
Since ResourceLib is meant to be thread safe, it synchronizes access to its data structures. However, simple data locking is not enough to ensure that loading threads cooperate. Consider a traditional approach for creation and library sharing of resources, which may include the following algorithm:
presource = Library.Get(resourceKey);
if (presource == NULL)
{
presource = LoadResource(resourceKey);
Library.Add(resourceKey, presource);
}
This logic can malfunction if several threads try to load the resource at the same time. Specifically, if thread B attempts to load a resource while thread A is already in the process of doing so, the logic above will end up loading it twice,wasting both memory and processing resources.
To avoid this problem ResourceLib the makes use of bind handles. The actual insertion of a resource therefore relies on the following logic:
ResourceLib::BindHandle bh; if (Library.BindResourceKey(&bh, resourceKey) == ResourceLib::RS_NeedsResolve) { presource = *LoadResource(resourceKey); if (presource) bh.ResolveResource(presource); else { bh.CancelResolve("error message); HandleError(); } } else { presource = *bh.WaitForResolve(); if (!presource) HandleError(); }
Here, the initial thread requesting the resource creates a bind handle and proceeds to resolve it if the bind status is RS_NeedsResolve. Once finished with loading, it resolves it with ResolveResource (or cancels loading with CancelResolve). Overall, BindResourceKey and BindHandle::ResolveResource calls are similar to the Get and Add calls in the earlier example. The major difference, however, occurs if a second thread comes in to load the resource while the first one is in the process of doing so. In this case the bind status returned by the BindResourceKey function will be RS_WaitingResolve, allowing the second thread to wait for resource loading completion. Once the first thread is done loading and resolves the resource, WaitForResolve will return the resource with its content appropriately shared.
Class |
Description |
Provides a way of locking resources so that one thread loads a resource at a time and prevents other threads to access the same resource at the same time. | |
Resource Slots which are allocated in a separate list during a lock. |
Enumeration |
Description |
An enumeration listing the bind status of the resources. |
Method |
Description |
Obtains a resource key and creates a bind handle to add resource to the library in a synchronized manner. | |
Obtains the heap that should be used for image allocations with this resource library. | |
Obtains the resource and delegates to Weak library. | |
Access resource list and is used for debug purposes. | |
Returns the AddRefed ResourceWeakLib pointer. | |
ResourceLib constructor. | |
Unpins all resources pinned to the resource library. |
GFx_Resource.h