Cache design: flyweight of mutable entity objects based on an immutable key - c++

A lot of different screens in my app refer to the same entity/business objects over and over again.
Currently, each screen refers to their own copy of each object.
Also, entity objects may themselves expose access to other entity objects, again new copies of objects are created.
I'm trying to find a caching solution.
I'm looking for something similar to boost::flyweight.
However, based on immutable key/mutable value and reference counted.
boost::flyweight<key_value<long, SomeObject>, tag<SomeObject> > object;
The above is almost perfect.
I'm looking for a similar container that will give mutable access to SomeObject
Edit:
I like the flyweight's syntax and semantics. However, flyweight only allows const SomeObject& access, no chance to modify the object.
Edit2: Code has to compile on MSVC++6
Any ideas?

As long as you are happy affecting intrinsic state, then from the internals in boost/flyweight/key_value.hpp it looks like you can get away with a const_cast. If you have your own key extractor you should ensure it doesn't vary with the operations that making x mutable will expose it to.
flyweight<key_value<long, SomeObject> > kvfw(2);
SomeObject &x = const_cast<SomeObject &>(static_cast<const SomeObject&>(kvfw));

I think if you make flyweights mutable, then they cannot be legally called flyweights. Imagine a situation where glyphs are represented as flyweights. What will happen if one function changes the codepoint of the glyph that represents the letter 'A'? Another function which render the glyphs on screen, will try to draw 'A' and the user might end up seeing 'B' or something else! I think you need immutable keys referring to mutable objects. Then, think of using a hash table coupled with some reference counting mechanism.

Related

C++ several instances (but not all) of a class sharing a vector

I want to have a class C, such that instances of C hold a std::vector<int> as a private member. Now many instances (but not all) of C will share that vector and keeping a copy for each instance is what I would want to avoid.
If this vector were a single integer for example, I could create a template class for C and have it like this:
template <int N>
class C {
// something
};
If instead of some instances I wanted all instances to share that vector then I would declare the variable static as
class C {
static std::vector<int> _vec;
What I am looking is for something intermediate. I could for example keep a shared_ptr as a private non-static member as in
class C {
std::shared_ptr<std::vector<int>> _vec;
}
And that would take care of the lifetime of the object, with some overhead for maintaining shared ownership and also an extra pointer per-instance. I could keep a reference instead and let the creator of the instances take care of the lifetime, but avoid the overhead of the shared_ptr. Is there a better approach to this design question?
…such that instances of C hold a std::vector as a private member. Now many instances (but not all) of C will share that vector
So, that's self-contradicting. You can't hold an instance and share the instance safely.
This is a classical use case of pointers; even more specifically, classical use case of a shared pointer, as you already noticed.
I could keep a reference instead and let the creator of the instances take care of the lifetime,
/me sounds the access-after-destruction alarm You're about to find out that won't work. The lifetime is not like you think, but ends when the owning object's lifetime ends. So, this breaks. (Also, you'll find that under the hood, handing out references compiles down to the same code as handing out raw pointers – it's just safer and does the dereferencing automagically within the language; you're not actually saving a memory indirection there. The classes containing the reference still need to know the address of the object they're handling, and that's the same as having a pointer, if you ask your CPU.)
It breaks, unless the thing handing out the references keeps a count on how many references it handed out, subtracts many references it handed out belong to C instances that were deconstructed, and then deconstructs the vector as soon as that number reaches 0. Take a wild guess what a shared_ptr does! Exactly this reference counting.
Often, however, the access logic is easier; for example,
I have a vector of C, std::vector<C> lexicon, and all held C._vec need to get removed exactly when that full lexicon goes out of scope, so I handle that manually
actually doesn't need reference counting and hence is lower-overhead. You can indeed solve that by handing out references – but I'd actually prefer to hand out raw pointers in that case: they just as much don't imply ownership, and you don't accidentally make a copy of the std::vector<int> when you pass the pointer by value.
If your lifetime tracking isn't as easy as that example :
There's no magic usage tracking in references; and you need something to keep track of whether something is still holding some handle to your individual vector. That tracking is exactly the "overhead" shared_ptr incurs. No way around it.
A private shared_ptr is hence the right approach:
class C {
private:
std::shared_ptr<std::vector<int>> _vec;
}
Your static approach takes you nowhere here - it only makes sense if all, and really all, instances share the same vector which should essentially live from the beginning of time till the end, and even then, it's a bit of a solution that can lead to additional headaches in form of the static initialization order fiasco. I'd advise to not do that under almost all circumstances.
(Plus, a static member also just boils down to the code looking up the same address – so, performance-wise, same as a pointer. Again, nothing really won here.)

Should I use reference member to deal with dependency between objects?

As a beginner in C++, I am practicing C++ with an algorithm assignment. Along the way, I have some questions that I have difficulty getting through. Pardon me if the questions sound entry-level since I am still learning.
The goal is to find collinear points in a given vector of points with three classes. The following briefly describes the three classes' purposes:
Point: Representing a point with x and y values.
LineSegment: Representing a line segment with two points at ends.
Collinear: Containing the segments found in a vector of Points. The main part of the algorithm.
So, I would expect the client code to look like this:
std::vector<Point> points; // may become huge
// populate points
// ...
Collinear collinear_points(points);
std::vector<LineSegment> segments_in_points = collinear_points.GetSegments();
Since the class Collinear depends on a certain vector of points to get the segments correspondingly, I think it would need it as a data member. The question that keeps haunting me is, should it hold a copy of the vector or hold a raw pointer/reference to the vector outside the object. I think a smart pointer would be an overkill here. According to the old answer here, maybe it is better to go with reference which also avoids potential expensive copying? What is the common practice for this kind of dependency between classes if any exists?
If points gets modified after the construction of collinear_points, then the data collinear_points is referencing will be inconsistent with the segments it contains. Is it common to leave the responsibility to users for making sure the validness of an object depending on other ones? Is there a way to let collinear_points know the content has been modified and put it in an invalid state?
To answer your actual question from the title: A non-owning raw pointer would still be the usual choice, mainly because that’s what we’ve been doing since the old C days. Of course, a pointer has the problem that it can be nullptr. So using a reference communicates more clearly that null is not an allowed value. Because of that I tend to use the reference, although it still feels a tiny bit weird even to myself. But imo it’s the better design decision overall
That said, I believe the real question here is one of ownership. If Collinear does not own the vector, the user of your API has to make sure that the vector lives at least as long as the associated Collinear object. Otherwise you’ll access a dangling pointer/reference and things tend to go downhill from there. ;)
Is there a way to let collinear_points know the content has been modified and put it in an invalid state?
Yes, there is. Own everything. That includes the points vector and the segments vector. Following this approach Collinear could look something like this:
class Collinear {
public:
// usings because I’m a lazy typer
using PointsVec = std::vector<Point>;
using SegmentsVec = std::vector<LineSegment>;
// Take ownership of the points vector by either copying
// or moving it into a member.
explicit Collinear(const PointsVec& p): m_points(p) {}
explicit Collinear(PointsVec&& p): m_points(std::move(p)) {}
// Retain ownership of the segments vector by returning a const ref.
const SegmentsVec& GetSegments(); // Check if you can make it const.
// access functions for the two vectors ...
private:
PointsVec m_points;
SegmentsVec m_segments;
}
Now Collinear controls access to the points vector. You’ll have to write the functions for the permitted operations as members of Collinear. The important thing is never to return a non-const pointer or non-const ref to m_points, because then you might miss write accesses.
The segments vector is similar. Your provide the write access member functions and Collinear retains ownership, which means it can re-calculate it when necessary and the user doesn’t need to be concerned with that. Depending on how expensive the calculation is you can now go wild with lazy evaluation and every optimization you can think of.
There is a completely different design approach, though. Own nothing. Does Collinear have to be a class at all? Could it be a bunch of free functions in a namespace?
namespace Collinear {
std::vector<LineSegment> GetSegments(const std::vector<Point>& points);
}
// ...
auto segments_in_points = Collinear::GetSegments(points);
That’s the opposite of the own-everything approach. Before, you had full control. Now your user has full control. On the other hand, they now have to take care of any laziness/optimizations/update detection.
Which approach is appropriate is a question of a) API design philosophy and b) your conrete situation. What are your users? What do they expect? Which approach makes their lives easier? Since this is an assignment, you probably won’t have any real users. So imagine a group of people that might want to use your code and decide based on that. Or just use the approach you’ll have more fun implementing. The important thing imo: Pick one of the two approaches. Don’t mix them, because such an API is inconsistent. That increases confusion, decreases ease of use, and makes errors more likely.
Btw:
I think a smart pointer would be an overkill here.
Using smart pointers is not a question of overkill. It’s a question of ownership. If you have an owning pointer never use a raw pointer for it. … Unless a legacy API forces you to. Even then it’s a great idea to mark it as owning with a transparent wrapper like gsl::owner<T>.
The question that keeps haunting me is, should it hold a copy of the vector or hold a raw pointer/reference to the vector outside the object
I think you should keep a copy of vector here to keep things generic.You don't want your collinear class depend on a particular vector<Points>, instead it should be like while creating instance of collinear class you just tell it on what vector<Points>, it has to work on.Then if you change this vector and you want collinear also to work on this data set(which you might not want), its your responsibility to tell collinear to work on new data set.If you want collinear to be updated automatically when you update vector<points>, you can do so, but you have to answer questions like what happens to the state of collinear(which would be depending on the vector<points>) when the data set changes.

Why should methods return a new instance, rather than modify the instance itself?

Suppose I have a Vector3 class, that contains a normalize() method. Should that method return a new Vector3, or modify the Vector3 instance it is called on (therefore returning a reference to itself (Vector3&)?) What are some instances where one would be preferred over the other? What about performance?
The answer depends on the design of your class.
For mutable classes rotate should rotate the vector itself. This is viewed as somewhat more efficient, and in case of large objects it lets you avoid copying large volumes of data when vectors have many items in them.
Immutable classes, on the other hand, must return only new objects, because they cannot be mutated themselves. This adds some overhead, but it has a lot of pluses, especially when objects must be used concurrently.
A common naming convention is to use a verb for mutating operations, as in
myVector.rotate(angle);
myVector.scale(factor);
while operations that return new objects should be named with past participles, as in
auto newVector = myVector.rotated(angle).scaled(factor);
Competing goals: Correctness vs Performance (sometimes).
If you use immutable types, you have it easier to write correct (parallel) programs. If you use mutable types, you sometimes have a certain performance benefit which might well be lost once you try to go parallel. Then there is the 80/20 rules. 80% of the code need not be optimized. So why use mutable types by default?
First go immutable, then see if it has enough performance, then optimize, if not.
Vector3 rotate(const Angle& angle)
is probably fine, but well depends on Vector3 is implemented correctly. Especially regarding std::move() behavior.
Side effects. If I pass an object that I retrieved from a map, for example, and you do something to the object I pass, you have changed the thing that is inside my map, and the next time I ask for it I get something that does not look the same as I got last time. Keeping objects immutable prevents accidents like this, especially when multiple devs are working on the same app.

C++ Is making objects depend on others a good design?

I have a basic design that consists of three classes : A Data class, A Holder class wich holds and manages multiple Data objects, and a Wrapper returned by the Holder wich contains a reference to a Data object.
The problem is that Wrapper must not outlive Holder, or it will contain a dangling reference, as Holder is responsible for deleting the Data objects. But as Wrapper is intended to have a very short lifetime (get it in a function, make some computation on its data, and let it go out of scope), this should not be a problem, but i'm not sure this is a good design.
Here are some solutions i thought about:
-Rely on the user reading the documentation, technically the same thing happens with STL iterators
-Using shared_ptr to make sure the data lasts long enought, but it feels like overkill
-Make Wrapper verify its Holder still exists each time you use it
-Any idea?
(I hope everyone can understand this, as english is not my native language)
Edit : If you want to have a less theoric approach, this all comes from a little algorithm i'm trying to write to solve Sudokus, the Holder is the grid, the Data is the content of each box (either a result or a temporary supposition), and the Wrapper is a Box class wich contains a reference to the Data, plus additional information like row and column.
I did not originally said it because i want to know what to do in a more general situation.
Only ever returning a Wrapper by value will help ensure the caller doesn't hold onto it beyond the calling scope. In conjunction with a comment or documentation that "Wrappers are only valid for the lifetime of the Holder that created them" should be enough.
Either that or you decide that ownership of a Data is transferred to the Wrapper when the Wrapper is created, and the Data is destroyed along with the Wrapper - but what if you want a to destroy a Wrapper without deleting the Data? You'd need a method to optionally relinquish ownership of the Data back to the Holder.
Whichever you choose, you need to decide what owns (ie: is responsible for the lifetime of) Data and when - once you've done that you can, if you want, use smart pointers to help with that management - but they won't make the design decision for you, and you can't simply say "oh I'll use smart pointers instead of thinking about it".
Remember, if you can't manage heap memory without smart pointers - you've got no business managing heap memory with them either!
To elaborate on what you have already listed as options,
As you suggested, shared_ptr<Data> is a good option. Unless performance is an issue, you should use it.
Never hold a pointer to Data in Wrapper. Store a handle that can be used to get a pointer to the appropriate Data object. Before Data is accessed through Wrapper, get a pointer the Data object. If the pointer is not valid, throw an exception. If the pointer is valid, proceed along the happy path.

Is it a good (correct) way to encapsulate a collection?

class MyContainedClass {
};
class MyClass {
public:
MyContainedClass * getElement() {
// ...
std::list<MyContainedClass>::iterator it = ... // retrieve somehow
return &(*it);
}
// other methods
private:
std::list<MyContainedClass> m_contained;
};
Though msdn says std::list should not perform relocations of elements on deletion or insertion, is it a good and common way to return pointer to a list element?
PS: I know that I can use collection of pointers (and will have to delete elements in destructor), collection of shared pointers (which I don't like), etc.
I don't see the use of encapsulating this, but that may be just me. In any case, returning a reference instead of a pointer makes a lot more sense to me.
In a general sort of way, if your "contained class" is truly contained in your "MyClass", then MyClass should not be allowing outsiders to touch its private contents.
So, MyClass should be providing methods to manipulate the contained class objects, not returning pointers to them. So, for example, a method such as "increment the value of the umpteenth contained object", rather than "here is a pointer to the umpteenth contained object, do with it as you wish".
It depends...
It depends on how much encapsulated you want your class to be, and what you want to hide, or show.
The code I see seems ok for me. You're right about the fact the std::list's data and iterators won't be invalidated in case of another data/iterator's modification/deletion.
Now, returning the pointer would hide the fact you're using a std::list as an internal container, and would not let the user to navigate its list. Returning the iterator would let more freedom to navigate this list for the users of the class, but they would "know" they are accessing a STL container.
It's your choice, there, I guess.
Note that if it == std::list<>.end(), then you'll have a problem with this code, but I guess you already know that, and that this is not the subject of this discussion.
Still, there are alternative I summarize below:
Using const will help...
The fact you return a non-const pointer lets the user of you object silently modify any MyContainedClass he/she can get his/her hands on, without telling your object.
Instead or returning a pointer, you could return a const pointer (and suffix your method with const) to stop the user from modifying the data inside the list without using an accessor approved by you (a kind of setElement ?).
const MyContainedClass * getElement() const {
// ...
std::list<MyContainedClass>::const_iterator it = ... // retrieve somehow
return &(*it);
}
This will increase somewhat the encapsulation.
What about a reference?
If your method cannot fail (i.e. it always return a valid pointer), then you should consider returning the reference instead of the pointer. Something like:
const MyContainedClass & getElement() const {
// ...
std::list<MyContainedClass>::const_iterator it = ... // retrieve somehow
return *it;
}
This has nothing to do with encapsulation, though..
:-p
Using an iterator?
Why not return the iterator instead of the pointer? If for you, navigating the list up and down is ok, then the iterator would be better than the pointer, and is used mostly the same way.
Make the iterator a const_iterator if you want to avoid the user modifying the data.
std::list<MyContainedClass>::const_iterator getElement() const {
// ...
std::list<MyContainedClass>::const_iterator it = ... // retrieve somehow
return it;
}
The good side would be that the user would be able to navigate the list. The bad side is that the user would know it is a std::list, so...
Scott Meyers in his book Effective STL: 50 Specific Ways to Improve Your Use of the Standard Template Library says it's just not worth trying to encapsulate your containers since none of them are completely replaceable for another.
Think good and hard about what you really want MyClass for. I've noticed that some programmers write wrappers for their collections just as a matter of habit, regardless of whether they have any specific needs above and beyond those met by the standard STL collections. If that's your situation, then typedef std::list<MyContainedClass> MyClass and be done with it.
If you do have operations you intend to implement in MyClass, then the success of your encapsulation will depend more on the interface you provide for them than on how you provide access to the underlying list.
No offense meant, but... With the limited information you've provided, it smells like you're punting: exposing internal data because you can't figure out how to implement the operations your client code requires in MyClass... or possibly, because you don't even know yet what operations will be required by your client code. This is a classic problem with trying to write low-level code before the high-level code that requires it; you know what data you'll be working with, but haven't really nailed down exactly what you'll be doing with it yet, so you write a class structure that exposes the raw data all the way to the top. You'd do well to re-think your strategy here.
#cos:
Of course I'm encapsulating
MyContainedClass not just for the sake
of encapsulation. Let's take more
specific example:
Your example does little to allay my fear that you are writing your containers before you know what they'll be used for. Your example container wrapper - Document - has a total of three methods: NewParagraph(), DeleteParagraph(), and GetParagraph(), all of which operate on the contained collection (std::list), and all of which closely mirror operations that std::list provides "out of the box". Document encapsulates std::list in the sense that clients need not be aware of its use in the implementation... but realistically, it is little more than a facade - since you are providing clients raw pointers to the objects stored in the list, the client is still tied implicitly to the implementation.
If we put objects (not pointers) to
container they will be destroyed
automatically (which is good).
Good or bad depends on the needs of your system. What this implementation means is simple: the document owns the Paragraphs, and when a Paragraph is removed from the document any pointers to it immediately become invalid. Which means you must be very careful when implementing something like:
other objects than use collections of
paragraphs, but don't own them.
Now you have a problem. Your object, ParagraphSelectionDialog, has a list of pointers to Paragraph objects owned by the Document. If you are not careful to coordinate these two objects, the Document - or another client by way of the Document - could invalidate some or all of the pointers held by an instance of ParagraphSelectionDialog! There's no easy way to catch this - a pointer to a valid Paragraph looks the same as a pointer to a deallocated Paragraph, and may even end up pointing to a valid - but different - Paragraph instance! Since clients are allowed, and even expected, to retain and dereference these pointers, the Document loses control over them as soon as they are returned from a public method, even while it retains ownership of the Paragraph objects.
This... is bad. You've end up with an incomplete, superficial, encapsulation, a leaky abstraction, and in some ways it is worse than having no abstraction at all. Because you hide the implementation, your clients have no idea of the lifetime of the objects pointed to by your interface. You would probably get lucky most of the time, since most std::list operations do not invalidate references to items they don't modify. And all would be well... until the wrong Paragraph gets deleted, and you find yourself stuck with the task of tracing through the callstack looking for the client that kept that pointer around a little bit too long.
The fix is simple enough: return values or objects that can be stored for as long as they need to be, and verified prior to use. That could be something as simple as an ordinal or ID value that must be passed to the Document in exchange for a usable reference, or as complex as a reference-counted smart pointer or weak pointer... it really depends on the specific needs of your clients. Spec out the client code first, then write your Document to serve.
The Easy way
#cos, For the example you have shown, i would say the easiest way to create this system in C++ would be to not trouble with the reference counting. All you have to do would be to make sure that the program flow first destroys the objects (views) which holds the direct references to the objects (paragraphs) in the collection, before the root Document get destroyed.
The Tough Way
However if you still want to control the lifetimes by reference tracking, you might have to hold references deeper into the hierarchy such that Paragraph objects holds reverse references to the root Document object such that, only when the last paragraph object gets destroyed will the Document object get destructed.
Additionally the paragraph references when used inside the Views class and when passed to other classes, would also have to passed around as reference counted interfaces.
Toughness
This is too much overhead, compared to the simple scheme i listed in the beginning. It avoids all kinds of object counting overheads and more importantly someone who inherits your program does not get trapped in the reference dependency threads traps that criss cross your system.
Alternative Platforms
This kind-of tooling might be easier to perform in a platform that supports and promotes this style of programming like .NET or Java.
You still have to worry about memory
Even with a platform such as this you would still have to ensure your objects get de-referenced in a proper manner. Else outstanding references could eat up your memory in the blink of an eye. So you see, reference counting is not the panacea to good programming practices, though it helps avoid lots of error checks and cleanups, which when applied the whole system considerably eases the programmers task.
Recommendation
That said, coming back to your original question which gave raise to all the reference counting doubts - Is it ok to expose your objects directly from the collection?
Programs cannot exist where all classes / all parts of the program are truly interdependent of each other. No, that would be impossible, as a program is the running manifestation of how your classes / modules interact. The ideal design can only minimize the dependencies and not remove them totally.
So my opinion would be, yes it is not a bad practice to expose the references to the objects from your collection, to other objects that need to work with them, provided you do this in a sane manner
Ensure that only a few classes / parts of your program can get such references to ensure minimum interdependency.
Ensure that the references / pointers passed are interfaces and not concrete objects so that the interdependency is avoided between concrete classes.
Ensure that the references are not further passed along deeper into the program.
Ensure that the program logic takes care of destroying the dependent objects, before cleaning up the actual objects that satisfy those references.
I think the bigger problem is that you're hiding the type of collection so even if you use a collection that doesn't move elements you may change your mind in the future. Externally that's not visible so I'd say it's not a good idea to do this.
std::list will not invalidate any iterators, pointers or references when you add or remove things from the list (apart from any that point the item being removed, obviously), so using a list in this way isn't going to break.
As others have pointed out, you may want not want to be handing out direct access to the private bits of this class. So changing the function to:
const MyContainedClass * getElement() const {
// ...
std::list<MyContainedClass>::const_iterator it = ... // retrieve somehow
return &(*it);
}
may be better, or if you always return a valid MyContainedClass object then you could use
const MyContainedClass& getElement() const {
// ...
std::list<MyContainedClass>::const_iterator it = ... // retrieve somehow
return *it;
}
to avoid the calling code having to cope with NULL pointers.
STL will be more familiar to a future programmer than your custom encapsulation, so you should avoid doing this if you can. There will be edge cases that you havent thought about which will come up later in the app's lifetime, wheras STL is failry well reviewed and documented.
Additionally most containers support somewhat similar operations like begin end push etc. So it should be fairly trivial to change the container type in your code should you change the container. eg vector to deque or map to hash_map etc.
Assuming you still want to do this for a more deeper reason, i would say the correct way to do this is to implement all the methods and iterator classes that list implements. Forward the calls to the member list calls when you need no changes. Modify and forward or do some custom actions where you need to do something special (the reason why you decide to this in the first place)
It would be easier if STl classes where designed to be inherited from but for efficiency sake it was decided not to do so. Google for "inherit from STL classes" for more thoughts on this.