I am currently designing an API and I am not sure whether my functions should take shared_ptr or weak_ptr. There are widgets that contain viewers. The viewers have a function add_painter which adds a painter to the viewer. When a viewer needs to redraw, it uses its painters to draw into a buffer and displays the result. I came to the conclusion that the viewers should hold the painters using weak_ptr:
A painter may be used in multiple viewers, so the viewer cannot own the painter.
Deleting the painter should remove it from the viewer. This way, users do not need to remember that they have to call a remove_painter function.
There may be different kind of viewers, so they are hidden behind an interface. What signature is best for the add_painter function in the interface?
Should I directly use void add_painter(weak_ptr<Painter> const& p)? This implies that the concrete implentations store the painters using weak_ptr, but I cannot enforce this: An implementation could just do painters.push_back(weak_ptr.lock()) and store a shared_ptr.
Should I use void add_painter(shared_ptr<Painter> const& p) instead? This implies that the viewers hold strong references, so that deleting a painter does not necessarily remove it from the viewer.
I also considered storing the painters directly in the interface class, but then it is no real interface anymore, is it?
You should not try to mitigate the Observer pattern with smart pointers and definitely you should avoid a situation when a client (View) can harass the server by converting the weak pointer to a shared pointer and storing it indefinitely barring it from being released by the server.
You should really consider the classic Observer pattern here requesting View to provide a painter_destroyed callback function. It may be an annoyance but also gives the client an opportunity to implement some additional actions once the painter is destroyed. Otherwise finding that the painter exists no more just when one wants to use it may be quite irritating and affect overall program performance.
Related
I've got some code that is using shared_ptr quite widely as the standard way to refer to a particular type of object (let's call it T) in my app. I've tried to be careful to use make_shared and std::move and const T& where I can for efficiency. Nevertheless, my code spends a great deal of time passing shared_ptrs around (the object I'm wrapping in shared_ptr is the central object of the whole caboodle). The kicker is that pretty often the shared_ptrs are pointing to an object that is used as a marker for "no value"; this object is a global instance of a particular T subclass, and it lives forever since its refcount never goes to zero.
Using a "no value" object is nice because it responds in nice ways to various methods that get sent to these objects, behaving in the way that I want "no value" to behave. However, performance metrics indicate that a huge amount of the time in my code is spent incrementing and decrementing the refcount of that global singleton object, making new shared_ptrs that refer to it and then destroying them. To wit: for a simple test case, the execution time went from 9.33 seconds to 7.35 seconds if I stuck nullptr inside the shared_ptrs to indicate "no value", instead of making them point to the global singleton T "no value" object. That's a hugely important difference; run on much larger problems, this code will soon be used to do multi-day runs on computing clusters. So I really need that speedup. But I'd really like to have my "no value" object, too, so that I don't have to put checks for nullptr all over my code, special-casing that possibility.
So. Is there a way to have my cake and eat it too? In particular, I'm imagining that I might somehow subclass shared_ptr to make a "shared_immortal_ptr" class that I could use with the "no value" object. The subclass would act just like a normal shared_ptr, but it would simply never increment or decrement its refcount, and would skip all related bookkeeping. Is such a thing possible?
I'm also considering making an inline function that would do a get() on my shared_ptrs and would substitute a pointer to the singleton immortal object if get() returned nullptr; if I used that everywhere in my code, and never used * or -> directly on my shared_ptrs, I would be insulated, I suppose.
Or is there another good solution for this situation that hasn't occurred to me?
Galik asked the central question that comes to mind regarding your containment strategy. I'll assume you've considered that and have reason to rely on shared_ptr as a communical containment strategy for which no alternative exists.
I have to suggestions which may seem controversial. What you've defined is that you need a type of shared_ptr that never has a nullptr, but std::shared_ptr doesn't do that, and I checked various versions of the STL to confirm that the customer deleter provided is not an entry point to a solution.
So, consider either making your own smart pointer, or adopting one that you change to suit your needs. The basic idea is to establish a kind of shared_ptr which can be instructed to point it's shadow pointer to a global object it doesn't own.
You have the source to std::shared_ptr. The code is uncomfortable to read. It may be difficult to work with. It is one avenue, but of course you'd copy the source, change the namespace and implement the behavior you desire.
However, one of the first things all of us did in the middle 90's when templates were first introduced to the compilers of the epoch was to begin fashioning containers and smart pointers. Smart pointers are remarkably easy to write. They're harder to design (or were), but then you have a design to model (which you've already used).
You can implement the basic interface of shared_ptr to create a drop in replacement. If you used typedefs well, there should be a limited few places you'd have to change, but at least a search and replace would work reasonably well.
These are the two means I'm suggesting, both ending up with the same feature. Either adopt shared_ptr from the library, or make one from scratch. You'd be surprised how quickly you can fashion a replacement.
If you adopt std::shared_ptr, the main theme would be to understand how shared_ptr determines it should decrement. In most implementations shared_ptr must reference a node, which in my version it calls a control block (_Ref). The node owns the object to be deleted when the reference count reaches zero, but naturally shared_ptr skips that if _Ref is null. However, operators like -> and *, or the get function, don't bother checking _Ref, they just return the shadow, or _Ptr in my version.
Now, _Ptr will be set to nullptr (or 0 in my source) when a reset is called. Reset is called when assigning to another object or pointer, so this works even if using assignment to nullptr. The point is, that for this new type of shared_ptr you need, you could simply change the behavior such that whenever that happens (a reset to nullptr), you set _Ptr, the shadow pointer in shared_ptr, to the "no value global" object's address.
All uses of *,get or -> will return the _Ptr of that no value object, and will correctly behave when used in another assignment, or reset is called again, because those functions don't rely upon the shadow pointer to act upon the node, and since in this special condition that node (or control block) will be nullptr, the rest of shared_ptr would behave as though it was pointing to nullptr correctly - that is, not deleting the global object.
Obviously this sounds crazy to alter std::pointer to such application specific behavior, but frankly that's what performance work tends to make us do; otherwise strange things, like abandoning C++ occasionally in order to obtain the more raw speed of C, or assembler.
Modifying std::shared_ptr source, taken as a copy for this special purpose, is not what I would choose (and, factually, I've faced other versions of your situation, so I have made this choice several times over decades).
To that end, I suggest you build a policy based smart pointer. I find it odd I suggested this earlier on another post today (or yesterday, it's 1:40am).
I refer to Alexandrescu's book from 2001 (I think it was Modern C++...and some words I don't recall). In that he presented loki, which included a policy based smart pointer design, which is still published and freely available on his website.
The idea should have been incorporated into shared_ptr, in my opinion.
Policy based design is implemented as the paradigm of a template class deriving from one or more of it's parameters, like this:
template< typename T, typename B >
class TopClass : public B {};
In this way, you can provide B, from which the object is built. Now, B may have the same construction, it may also be a policy level which derives from it's second parameter (or multiple derivations, however the design works).
Layers can be combined to implement unique behaviors in various categories.
For example:
std::shared_ptr and std::weak_ptrare separate classes which interact as a family with others (the nodes or control blocks) to provide smart pointer service. However, in a design I used several times, these two were built by the same top level template class. The difference between a shared_ptr and a weak_ptr in that design was the attachment policy offered in the second parameter to the template. If the type is instantiated with the weak attachment policy as the second parameter, it's a weak pointer. If it's given a strong attachment policy, it's a smart pointer.
Once you create a policy designed template, you can introduce layers not in the original design (expanding it), or to "intercept" behavior and specialize it like the one you currently require - without corrupting the original code or design.
The smart pointer library I developed had high performance requirements, along with a number of other options including custom memory allocation and automatic locking services to make writing to smart pointers thread safe (which std::shared_ptr doesn't provide). The interface and much of the code is shared, yet several different kinds of smart pointers could be fashioned simply by selecting different policies. To change behavior, a new policy could be inserted without altering the existing code. At present, I use both std::shared_ptr (which I used when it was in boost years ago) and the MetaPtr library I developed years ago, the latter when I need high performance or flexible options, like yours.
If std::shared_ptr had been a policy based design, as loki demonstrates, you'd be able to do this with shared_ptr WITHOUT having to copy the source and move it to a new namespace.
In any event, simply creating a shared pointer which points the shadow pointer to the global object on reset to nullptr, leaving the node pointing to null, provides the behavior you described.
Sometimes it's convenient to split interface of some system/library in more than one class.
For example, consider idea of library for playing Chess. Its interface would use (and deliver to players) different object for every single game and - during game - another object for every figure.
In Java there wouldn't be such a problem. But in C++, a library user can delete (or make attempt to delete) every pointer he'll get. Even shared_ptr/weak_ptr.
What do you think about such situations? Should I use in my interface wrapping classes that deleting isn't dangerous?
What is an usual way for such dilemmas?
Is there a way that STL smart pointers would help? I heard that they should be used always and only to express ownership, so they seem to have nothing to do with this issue (Chess is owner of SingleGame, SingleGame is owner of every Figure).
PS did I use correct tags/subject?
You can't stop a user from breaking stuff. As others have suggested, use smart pointers. With C++11, there is no reason not to use them in new code. If the user still breaks it, that's their fault. You can't design a library that is completely foolproof. You can just do your best to disuade foolish behavior.
As others have said, smart pointers (or other RAII schemes) are often a great idea. They can clearly indicate ownership and at the same time provide an automatic mechanism for managing it. Try using such if you can.
But really, no reasonable C++ programmer should be blindly calling delete on every pointer they get. When they use a library/API/whatever which returns a pointer/handle/resource/etc they should be reading its documentation to tell them whether or not they will be responsible for deallocation and if so then when technique should be used.
So at a minimum, just make sure your public interface clearly indicates when ownership is passed to the caller and what method they should use for cleanup.
I am having some issues designing the memory management for an Entity-Component system and am having some issues coming up with the detail of the design. Here is what I am trying to do (note that all of these classes except Entity are actually virtual, so will have many different specific implementations):
The Program class will have a container of Entity's. The Program will loop through the Entity's and call update on each of them. It will also have a few SubSystem's, which it will also update on each loop through.
Each Entity will contain two types of Component's. All of them will be owned by a unique_ptr inside the Entity since their lifetime is directly tied to the entity. One type, UpdateableComponent, will be updated when the Entity.update() method is called. The second type SubSystemComponent will be updated from within their respective SubSystem.
Now here are my two problems. The first is that some of the Component's will control the lifetime of their parent Entity. My current idea for this is that Component will be able to call a function parent.die() which would change an internal flag inside Entity. Then after Program finishes looping through its updates, it loops through a second time and removes each Entity which was marked for deletion during the last update. I don't know if this is an efficient or smart way to go about it, although it should avoid the problem of an Entity dieing while its Component's are still updating.
The second issue is that I am not sure how to reference SubSystemComponent's from within SubSystem. Since they are refered to by a unique_ptr from inside Entity, I can't use a shared_ptr or a weak_ptr, and a standard pointer would end up dangling when the Entity owning a component dies. I could switch to a shared_ptr inside the Entity for these, then use a weak_ptr in the SubSystem's, however I would prefer to not do this because the whole point is that Entity completely owns its Component's.
So 2 things:
Can my first idea be improved upon in a meaningful way?
Is there an easy way to implement a weak_ptr sort of functionality with unique_ptr, or should I just switch to shared_ptr and just make sure to not create more than one shared_ptr to the SubSystemComponent's
Can my first idea be improved upon in a meaningful way?
Hard to say without knowing more about the nature of the work being undertaken. For example, you haven't said anything about your use of threads, but it seems your design gives equal priority to all the possible updates by cycling through things in a set sequence. For some things where low latency is important, or there's some useful prioritorisation that would ideally be done, a looping sequence like that isn't good, while other times it's ideal.
There are other ways to coordinate the Component-driven removal of Entities from the Program:
return codes could bubble up to the loop over entities, triggering an erase from the container of Entities,
an Observer pattern or lambda/std::function could allow the Program to specify cleanup behaviour.
Is there an easy way to implement a weak_ptr sort of functionality with unique_ptr,
No.
or should I just switch to shared_ptr and just make sure to not create more than one shared_ptr to the SubSystemComponent's
It sounds like a reasonable fit. You could even wrap a shared_ptr in a non-copyable class to avoid accidental mistakes.
Alternatively - as for Entity destruction above - you could coordinate the linkage between SubSystem and SubSystemComponent using events, so the SubSystemComponent destructor calls back to the SubSystem. An Observer pattern is one way to do this, a SubSystemComponent-side std::function fed a lambda is even more flexible. Either way, the Subsystem removes the SubSystemComponent from its records.
I'm trying to write a simple event manager class and listeners for a game engine. In the usual implementation (i.e. McShaffry) the event manager registers listeners which in principle saves a shared_ptr to the listener as a private member.
I have seen in many instances people saying that shared_ptr and the likes should be avoided (eg here). Thus, I'm trying to find ways to implement the event manager without sharing ownership of the listeners.
One method I've thought of, is assigning unique ids to the listeners and register their ids with the event manager. Then the listeners are responsible of 'asking' the event manager after it has updated, if any events are available under their id.
I would like to ask if there are cleaner and/or standard methods to avoid shared ownership in this case, but also generally. For example, I have the same problem with the listeners. The listeners need to store a pointer to their parent (or the object for which they are listening) so that they can call its methods when handling an event.
As Mat’s comment says, there’s no reason not to use smart pointers in general. That said, the cautionary warning does seem to apply in your situation: as far as I understand you don’t have shared ownership; the event manager has sole ownership of the listeners. A shared_ptr would thus be inappropriate here.
An alternative would be to use a unique_ptr which is in many ways the other side of the shared_ptr coin. But depending on how you model listeners even that can be avoided by simply saving concrete instances to the event manager. Without a more detailed description it’s impossible to say whether you need pointers at all but if you don’t need them then, yes, the advice applies: don’t use (smart) pointers when concrete objects would do.
Finally, if your listeners are objects whose ownership is managed elsewhere consider simply using raw pointers to those objects: in that case, the event manager isn’t at all owner of the object – neither the sole nor a shared owner. While this would be the preferred way for me, it requires careful analysis about the listeners’ life-time to ensure that the event manager doesn’t point to listeners which don’t exist any more.
shared_ptr tends to be overused; it is often recommended, for example, on SO as a solution to vaguely stated pointer problems. It is not a substitute for good design, and should not be used unless there is a design in place that is based on understanding object lifetime issues in the code being written.
From personal experience, shared_ptrs a great, but sometimes may not be the correct tool for the job. If the code is entirely under your control, 99.9% of the time, shared_ptr will likely make your life easier. You do need to make sure you don't do thinks like:
Foo *f = new Foo();
shared_ptr<Foo> fptr(f);
shared_ptr<Foo> fptr2(f);
This will cause the memory for f to be deallocated with either fptr1 or fptr2. Instead you want to do something like:
Foo *f = new Foo();
shared_ptr<Foo> fptr(f);
shared_ptr<Foo> fptr2 = fptr;
In the second case, the assignment of one shared pointer to another will increment the reference count.
Another place where you can get in trouble with shared_ptr is if you need to pass a naked pointer to a function (this might occur if you need to pass this as the first parameter to a method, or you are relying on a 3rd party library). You can get the naked pointer from the shared_ptr, but you aren't guaranteed the memory address it's pointing to will still be around, as the reference counter won't be incremented.
You can around this by keeping an additional shared_ptr, though this can be a hassle.
There are other forms of smart pointers. For example, OpenSceneGraph has a ref_ptr which is easier to work with than shared_ptr. The one caveat, is that all objects it points to must descend from Referenced. However, if you're okay with that, I think it's a lot more difficult to have really bad things happen.
In some cases shared_ptr is overkill or doesn't properly exibhit the desired semantics (for example passing ownership).
What you need to do is look at your design and see what ownership model you need. If you need/want shared ownership then just use shared_ptr to model that. If a shared/ref counted ownership is not appropriate use another smart pointer.
Wouldn't your case be a good fit for a nice use of auto_ptr described here : http://www.gotw.ca/publications/using_auto_ptr_effectively.htm (guru of the week «using auto_ptr effectively)
For what I understand, you build a listener, then give it to an event manager. So the event manager can be seen as a "sink".
With the auto_ptr technique, your event manager can cleanly and safely take full ownership of the listener you give him.
What is a good way to share an instance of an object between several classes in a class hierarchy? I have the following situation:
class texture_manager;
class world {
...
std::vector<object> objects_;
skybox skybox_;
}
I currently implemented texture_manager as a singleton, and clients call its instancing method from anywhere in the code. texture_manager needs to be used by objects in the objects_ vector, by skybox_, and possibly by other classes as well that may or may not be part of the world class.
As I am trying to limit the use of singletons in my code, do you recommend any alternatives to this approach? One solution that came to mind would be to pass a texture_manager reference as an argument to the constructors of all classes that need access to it. Thanks.
The general answer to that question is to use ::std::shared_ptr. Or if you don't have that, ::std::tr1::shared_ptr, or if you don't have that, ::boost::shared_ptr.
In your particular case, I would recommend one of a few different approaches:
One possibility is, of course, the shared_ptr approach. You basically pass around your pointer to everybody who needs the object, and it's automatically destroyed when none of them need it anymore. Though if your texture manager is going to end up with pointers to the objects pointing at it, you're creating a reference cycle, and that will have to be handled very carefully.
Another possibility is just to declare it as a local variable in main and pass it as a pointer or reference to everybody who needs it. It won't be going away until your program is finished that way, and you shouldn't have to worry about managing the lifetime. A bare pointer or reference is just fine in this case.
A third possibility is one of the sort of vaguely acceptable uses of something sort of like a singleton. And this deserves a detailed explanation.
You make a singleton who's only job is to hand out useful pointers to things. A key feature it has is the ability to tell it what thing to hand out a pointer to. It's kind of like a global configurable factory.
This allows you to escape from the huge testing issues you create with a singleton in general. Just tell it to hand out a pointer to a stub object when it comes time to test things.
It also allows you to escape from the access control/security issue (yes, they create security issues as well) that a singleton represents for the same reason. You can temporarily tell it to pass out a pointer to an object that doesn't allow access to things that the section of code you're about to execute doesn't need access to. This idea is generally referred to as the principle of least authority.
The main reason to use this is that it saves you the problem of figuring out who needs your pointer and handing it to them. This is also the main reason not to use it, thinking that through is good for you. You also introduce the possibility that two things that expected to get the same pointer to a texture manager actually get pointers to a different texture manager because of a control flow you didn't anticipate, which is basically the result of the sloppy thinking that caused you to use the Singleton in the first place. Lastly, Singletons are so awful, that even this more benign use of them makes me itchy.
Personally, in your case, I would recommend approach #2, just creating it on the stack in main and passing in a pointer to wherever it's needed. It will make you think more carefully about the structure of your program, and this sort of object should probably live for your entire program's lifetime anyway.