Boost logo

Boost :

Subject: Re: [boost] [flyweight] key value with objects not constructible from a key
From: Mathias Gaunard (mathias.gaunard_at_[hidden])
Date: 2008-11-11 18:47:50


Michael Marcin wrote:

> The name factory for what is currently in place is misleading. Isn't it
> really just an associative container?

The name factory is only used to refer to the internal mechanism
Boost.Flyweight uses to store all elements.

Boost.Flyweight is neither a factory nor a a container, it is a smart
reference (in lack of a better name).
flyweight<T> aims at being the same at T, except it will use sharing
behind the scenes to reduce memory usage (each flyweight<T> is actually
a reference to some T stored in a flyweight factory shared between all
instances).

Also, you're saying it's not a factory but really an associative
container, while a factory is defined as being an associative container
in Boost.Flyweight.

> I'm trying to use flyweight to represent texture objects right now.
> These are surely a good candidate for use with flyweight as they are one
> of the examples given.

And the example really tells everything about how it should be done.

> My textures are fairly simple objects, with low
> coupling. Creating a texture is however expensive and has a lot of
> dependencies (libjpeg,libpng,etc). I typically have a TextureFactory
> which decouples the construction of a texture from the actual texture
> object and allows the work required to setup the various libraries to
> read images to be reused by all textures constructed from the same
> TextureFactory instance.
>
> It doesn't seem possible to have this decoupling with flyweight.
> Am I missing something?

The thing is you're not create a factory or perform decoupling at all.
The goal of boost::flyweight is to do that for you.

So you just write

struct texture
{
     texture(const std::string& name)
     {
        /* load up my texture */
     }

     ...
};

And then you have a texture, which can be constructed independently of
any other instance without any factory or anything, which doesn't share
state with anyone etc. Basically, a fairly normal value type with eager
evaluation, with the advantages and disadvantages it means.

And that's when flyweight kicks in. It will turn any type into a
memoized one, using a global table behind the scenes.

Boost.Flyweight does this by taking an object of such a type, seeing if
it is in a global table, and behaving as a reference to that object in
the table. If the object is not in the table, it is added.

The problem, however, is that this approach requires the object to be
constructed *before* the look-up, which is potentially useless if it's
already in the table.
The basic idea is then to be able to provide the constructor arguments
instead of the object itself, and use those arguments as key for the
look-up or for creating the object if needed. That is what
Boost.Flyweight does under the key_value name.

flyweight<T> could be implemented in terms of flyweight<key_value<T, T,
self_extractor> >.

If there is some specific thing you want to customize, changing the
factory, holder, locking ou tracking policy to custom ones is also possible.
The factory defines the associative container being used.
The holder defines how the factory is stored.
Locking policy and tracking policies seem self-explanatory.

You can even do garbage collection by using no tracking and doing the
work in the factory. May not be a very elegant design however.


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk