Flyweights with Boost and external data sources
Asked Answered
R

3

7

Maybe there is a simple way around this that I'm not seeing, so hopefully somebody can explain it to me.

Let's say I have a class:

class A {
public:
  const double parameter;
  const std::string name;
  const std:: string fileName;

  A(const double parameter, const std::string name, const std::string fileName) : 
      parameter(parameter), name(name), fileName(fileName) {}; 
};

And the generator for that class is:

class AReader {
public:
  ifstream dataFile;
  AReader(const std::string filename);
  A* readObject(const std::string objectName);
};

I would like to use boost::flyweight to handle these A objects because there will be potentially millions of references to them and in reality they contain a lot of data. They will be hashed on name and fileName together.

What do I need to make this work? I need the boost::flyweight to call AReader.readObject and hash/store the resulting A class.

Does the AReader need to become a full factory and used as a custom factory? Or is it possible to use the default factory in the flyweight and somehow use AReader to generate the A instances (as opposed to implementing the entire storage pattern required by the factory), maybe by making an AReader instance an argument to something in the flyweight? Or is it possible to get const public variables (ie. once set, they don't change) from an external data source without resorting to a second class?

Edit

I'm also open to other suggestions not using Boost. I can certainly write my own implementation of a flyweight, or any other pattern if one is better suited. But if I can use something that already exists, that would be best. Whatever minimizes the amount of code I need to write because, as always, deadlines are short.

Renfrow answered 13/1, 2012 at 16:39 Comment(0)
S
1

I haven't used Boost::flyweight but from the looks of it at the very least the key needs to be Assignable (in addition to being EqualityComparable and Hashable). With your const members you type is clearly not Assignable. From the looks of it, you don't have to make it Assignable if you have a key extractor. Using a key extractor only the key needs to be Assignable.

Studied answered 13/1, 2012 at 23:47 Comment(1)
That handles what needs to be done to get A into the flyweight (key extractor rather than assignable), but is the only way to use a helper-class that generates A to make it a full-blown factory to be used by the flyweight (implementing the storage and other methods required)?Renfrow
N
0

The basic way to use flyweight in your case is for readObject to return a flyweight. Internally, readObject creates a brand new object, and when you create the corresponding flyweight object, it then checks whether the object is already within the flyweight store. If so, it will drop your new object, and return a flyweight referencing the object in the store. If not, it adds the new object to its pool.

Now, this should be trivial to implement, but depending on your use case could be inefficient. For better performances, you can use the key_value functionality, which allows you to reference objects through their key, and only create them if they are not already present in the store.

Nicobarese answered 21/1, 2012 at 19:51 Comment(0)
B
0

Although a key_value Flyweight seems to fit the bill, it would seem there's a minor hitch. You should be able to construct a key_value Flyweight by using just one parameter of the key type (key_value flyweights). So to make it work with the key you want (filename+name) you'd have to pack those 2 fields in one (tuple? not even sure that'd work.)

Assuming you're interested in getting the most with the least amount of work, why not just Flyweight the strings in your class as demonstrated in Flyweight Basics?

This means A objects aren't hashed the way you want, but strings are easily flyweighted, and these seem to be your memory-problematic fields. (unless this is an oversimplification)

Blockish answered 22/1, 2012 at 12:6 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.