[flyweight] extending flyweight

Unfortunately I didn't have time to participate in the review of flyweight but I did follow it. Now that it has been accepted I'm looking into using it as a replacement for my homebrew mechanism. We currently have a Factory which we pass a hash id (which happens to be the hash of the lowercase filename using Bob Jenkin's lookup3 hash). The Factory then looks to the Cache to see if the object is already cached (i.e. exists in its collection which happens to be a boost::ptr_map of hash ids to the shared Resource). If its not in the Cache we pass the hash to the Repository which uses it to lookup and load the resource from an archive on disk. We then return the reference to the Cache's resource as a boost::cref<Resource>. Memory is very constrained and performance is important. We don't use reference counting but have designed the application so that there are places we can safely clear all the caches with no dangling references. I see that there is a no_tracking policy which allows us to skip reference counting. Is there a way to clear all Flyweight factories when using the no_tracking policy (the equivalent of our Caches IIUC)? A bonus would be to easily switch to the refcounted tracking policy and assert or throw when we try to clear all the factories if there are any outstanding references as a debugging aid. I tried to replace a simple part of the application that is using the homebrew mechanism with Boost.Flyweight and I ran into some problems. The current code looks like: std::auto_ptr<SoundInstance> CreateSound( unsigned int soundId ) { const Sound& sound = ResourceFactory::Instance()->Get<Sound>(soundId); return std::auto_ptr<SoundInstance>( new SoundInstance(sound) ); } I would think the new code would look like: std::auto_ptr<SoundInstance> CreateSound( unsigned int soundId ) { boost::flyweight<Sound> sound( soundId ); return std::auto_ptr<SoundInstance>( new SoundInstance(sound) ); } I need to create a factory that takes Resource hashes and loads resources which it caches in an unordered_ptr_set and then returns a reference to that cached resource. I then need to be able to clear the cached resources of the factory explicitly. I would like to store boost::flyweight<Resource> instead of const Resource& but I need to make sure that boost::flyweight<Resource> is the same size as a pointer to the Resource given proper policies (since the memory requirements are stringent). Is this possible with the current version? Is it a reasonable to apply flyweight in this manner? Thanks, Michael Marcin

Hello Michael, excuse my late answering. Michael Marcin <mmarcin <at> method-solutions.com> writes:
Unfortunately I didn't have time to participate in the review of flyweight but I did follow it. Now that it has been accepted I'm looking into using it as a replacement for my homebrew mechanism.
We currently have a Factory which we pass a hash id (which happens to be the hash of the lowercase filename using Bob Jenkin's lookup3 hash). The Factory then looks to the Cache to see if the object is already cached (i.e. exists in its collection which happens to be a boost::ptr_map of hash ids to the shared Resource). If its not in the Cache we pass the hash to the Repository which uses it to lookup and load the resource from an archive on disk. We then return the reference to the Cache's resource as a boost::cref<Resource>.
This case of use is suitable for the keyed_flyweight variant that Alberto and I discussed during the review, please see: http://lists.boost.org/Archives/boost/2008/02/132940.php (some code attached). The current lib does not have keyed_flyweight, vut it will include it (or something similar) before the library is first commited to the Boost SVN.
Memory is very constrained and performance is important. We don't use reference counting but have designed the application so that there are places we can safely clear all the caches with no dangling references. I see that there is a no_tracking policy which allows us to skip reference counting. Is there a way to clear all Flyweight factories when using the no_tracking policy (the equivalent of our Caches IIUC)?
This will be doable with the future introspection API, which will allow the user to access the internal components of the flyweight type, in this case the factory, and manage them: http://svn.boost.org/svn/boost/sandbox/flyweight/libs/flyweight/doc/ future_work.html#instrospection
A bonus would be to easily switch to the refcounted tracking policy and assert or throw when we try to clear all the factories if there are any outstanding references as a debugging aid.
This is also doable: a suggestion was made during the review that ref_counted elements should raise an assert failure when they're being deleted and their refcount!=0, which is what you need if I got you right.
I tried to replace a simple part of the application that is using the homebrew mechanism with Boost.Flyweight and I ran into some problems.
The current code looks like:
std::auto_ptr<SoundInstance> CreateSound( unsigned int soundId ) { const Sound& sound = ResourceFactory::Instance()->Get<Sound>(soundId); return std::auto_ptr<SoundInstance>( new SoundInstance(sound) ); }
I would think the new code would look like:
std::auto_ptr<SoundInstance> CreateSound( unsigned int soundId ) { boost::flyweight<Sound> sound( soundId ); return std::auto_ptr<SoundInstance>( new SoundInstance(sound) ); }
I need to create a factory that takes Resource hashes and loads resources which it caches in an unordered_ptr_set and then returns a reference to that cached resource. I then need to be able to clear the cached resources of the factory explicitly.
As explained above the current "classic" flyweight does not allow to have a key different than the stored value itself, but keyed_flyweight will.
I would like to store boost::flyweight<Resource> instead of const Resource& but I need to make sure that boost::flyweight<Resource> is the same size as a pointer to the Resource given proper policies (since the memory requirements are stringent).
Yep, this is the case for all built-in factories provided by the lib (the size of the flyweight is just the size of the internal handle type associated to the factory). This I'll make explicit in the upcoming performance section.
Is this possible with the current version? Is it a reasonable to apply flyweight in this manner?
Well, yours is a demanding scenario, but I hope the changes I'll do to the lib will cope with your needs. The current version of the library is too limited for what you're after. Joaquín M López Muñoz Telefónica, Investigación y Desarrollo

Joaquín M LópezMuñoz wrote:
Is this possible with the current version? Is it a reasonable to apply flyweight in this manner?
Well, yours is a demanding scenario, but I hope the changes I'll do to the lib will cope with your needs. The current version of the library is too limited for what you're after.
Awesome, I look forward to the updates and when they are ready I will make another push towards replacing our caching with Flyweight. Thanks, Michael Marcin
participants (2)
-
Joaquín M López Muñoz
-
Michael Marcin