Sign in to follow this  

Boost::flyweight

This topic is 3597 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Very interesting And, it's been accepted. Depending on how well implemented it is (well, it's good, but is it suitable), this makes component based approach considerably more practical. And, apparently even supports serialization. If anything, this is one of very practical toolkits for networked games.

Share this post


Link to post
Share on other sites
I've applied the underlying concept before, but never really thought of it as a pattern until now. Basically, if you have a large number of objects with a much smaller number of state permutations, you store all the different states once in a table and give each object a reference to its state. Throw in a reverse mapping if you need it, and/or a reference count for cleanup of unused state. The solution just arose naturally during memory optimization :) String tables immediately come to mind...

But it will be nice to have a Boost object that formally encapsulates this pattern :)

Share this post


Link to post
Share on other sites
This is, well, exactly what I designed my resource managers to do. And I spent a good deal of time designing and writing the system, too.

I never knew that it was known offically as the "flyweight pattern". If only this had shown up a bit earlier, it would have saved me a lot of trouble.[grin]

Share this post


Link to post
Share on other sites
I always found the Flyweight pattern to be a bit like Singletons in that it's very easy to mislead yourself into using it for the wrong purpose, ie. treating the shared data as part of the object when sometimes it should be a separate object. (eg. I would have one object for Legolas and one for Elf, and the former would reference the latter, but they would be of different types and maintained separately.) But I guess that in some situations, it is nice to have it done automatically (eg. the names example given in the linked page).

It doesn't help that "The classical example of application of the flyweight idiom" is quite ridiculous, because you wouldn't apply "font, size, typesetting effects, etc." to individual letters, but to ranges of text. Implementing each letter as a flyweight would still be incredibly heavyweight compared to marking style regions and so on.

Another thing that bothers me slightly is that it's designed to save memory... but it doesn't appear very easy to see how much memory is saved using this library, if any. Is there some function I'm missing that allows you to query how often each shared item is used, for example?

Share this post


Link to post
Share on other sites
Quote:
Original post by Kylotan
Another thing that bothers me slightly is that it's designed to save memory... but it doesn't appear very easy to see how much memory is saved using this library, if any. Is there some function I'm missing that allows you to query how often each shared item is used, for example?


Pointer-per-flyweight. Storage likely requires std::set entry.

And yes, the canonical example is borked. It doesn't usually apply to character per-se, settings are applied to range, but range attributes themselves are flyweight.

Whenever you create a flyweight, you use a factory. If the value for flyweight exists, pointer to this instance is returned. If it doesn't, new object is created, stored in some container, and pointer to it is returned.

This is useful for strings. For example, flyweight<std::string> monsterName;

Here, using database driven world population, you simply create monsterName directly from file or DB input. Yet, all "Small Orc" will share same instance of string, without you being aware of background management routines.

It's obviously not suitable for objects smaller than sizeof(void*), unless it uses boost::any-like approach which, for such objects, allocates them in-place.

One important detail is memory management. Do the allocated objects that are no longer used get de-allocated? If so, when?

Share this post


Link to post
Share on other sites
Quote:
Original post by Antheus
Pointer-per-flyweight. Storage likely requires std::set entry.


Yeah, but I'd like to be able to see how much sharing is actually going on, without having to add my own parallel debug counting. Without that metric, it appears to be a completely speculative optimisation. If a use case is to save memory, then surely there has to be some way of measuring that, at least in terms of objects if not in terms of bytes.

Quote:
One important detail is memory management. Do the allocated objects that are no longer used get de-allocated? If so, when?


This bit shows that you can have ref-counted ones (larger, but don't persist beyond their usefulness) and untracked ones (the opposite). So that's good.

Share this post


Link to post
Share on other sites

This topic is 3597 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

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