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.
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.
I'm having trouble getting things organized properly with smart pointers. Almost to the point that I feel compelled to go back to using normal pointers.
I would like to make it easy to use smart pointers throughout the program without having to type shared_ptr<...> every time. One solution I think of right away is to make a template class and add a typedef sptr to it so I can do class Derived : public Object < Derived > .. and then use Derived::sptr = ... But this obviously is horrible because it does not work with another class that is then derived from Derived object.
And even doing typedef shared_ptr<..> MyObjectPtr is horrible because then it needs to be done for each kind of smart pointer for consistency's sake, or at least for unique_ptr and shared_ptr.
So what's the standard way people use smart pointers? Because frankly I'm starting to see it as being too much hassle to use them. :/
So what's the standard way people use smart pointers?
Rarely. The fact that you find it a hassle to use them is a sign that you over-use pointers. Try to refactor your code to make pointers the exception, not the rule. shared_ptr in particular has its niche, but it’s a small one: namely, when you genuinely have to share ownership of a resource between several objects. This is a rare situation.
Because frankly I'm starting to see it as being too much hassle to use them. :/
Agreed. That’s the main reason not to use pointers.
There are more ways to avoid pointers. In particular, shared_ptr really only needs to spelled out when you actually need to pass ownership. In functions which don’t deal with ownership, you wouldn’t pass a shared_ptr, or a raw pointer; you would pass a reference, and dereference the pointer upon calling the function.
And inside functions you almost never need to spell out the type; for instance, you can (and should) simply say auto x = …; instead of shared_ptr<Class> x = …; to initialise variables.
In summary, you should only need to spell out shared_ptr in very few places in your code.
I have a lot of code that creates objects dynamically. So using pointers is necessary because the number of objects is not known from the start. An object is created in one subsystem, then stored in another, then passed for further processing to the subsystem that created it. So that I guess means using shared_ptr. Good design? I don't know, but it seems most logical to ask subsystem to create a concrete object that it owns, return a pointer to an interface for that object and then pass it for further processing to another piece of code that will interact with the object through it's abstract interface.
I could return unique_ptr from factory method. But then I would run into trouble if I need to pass the object for processing multiple times. Because I would still need to know about the object after I pass it to another method and unique_ptr would mean that I lose track of the object after doing move(). Since I need to have at least two references to the object this means using shared_ptr.
I heard somewhere that most commonly used smart pointer is unique_ptr. Certainly not so in my application. I end up with using shared_ptr mush more often. Is this a sign of bad design then?
Generally I follow the Google style guide, which I feel aligns nicely with the way I see things. I also, almost exclusively, use boost::scoped_ptr so that only a single manager has ownership of a particular object. I then pass around naked pointers, the idea being that my projects are structured such that the managers of said objects are always destroyed after the objects that use them are destroyed.
http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml#Smart_Pointers
This is all great, however I was just bitten by a nasty little memory stomp bug where the owner just so happened to be deleted before objects that were using it were deleted.
Now, before everyone jumps up and down that I'm a fool for this pattern, why don't I just use shared_ptr ? etc., consider the point that I don't want to have undefined owner semantics. Although shared_ptr would have caught this particular case, it sends the wrong message to users of the system. It says, "I don't know who owns this, it could be you!"
What would have helped me would have been a weak pointer to a scoped pointer. In effect, a scoped pointer that has a list of weak references, that are nulled out when the scoped pointer destructs. This would allow single ownership semantics, but give the using objects a chance to catch the issue I ran into.
So at the expense of an extra 'weak_refs' pointer for the scoped_ptr and an extra pointer for the 'next_weak_ptr' in the weak_ptr, it would make a neat little single owner, multiple user structure.
It could maybe even just be a debug feature, so in 'release' the whole system just turns back into a normally sized scoped_ptr and a standard single pointer for the weak reference.
So..... my QUESTIONS after all of this are:
Is there such a pointer/patten already in stl/boost that I'm
missing, or should I just roll my own?
Is there a better way, that
still meets my single ownership goal?
Cheers,
Shane
2. Is there a better way, that still meets my single ownership goal?
Do use a shared_ptr, but as a class member so that it's part of the invariant of that class and the public interface only exposes a way to obtain a weak_ptr.
Of course, pathological code can then retain their own shared_ptr from that weak_ptr for as long as they want. I don't recommend trying to protect against Machiavelli here, only against Murphy (using Sutter's words). On the other hand, if your use case is asynchronous, then the fact that locking a weak_ptr returns a shared_ptr may be a feature!
Although shared_ptr would have caught this particular case, it sends the wrong message to users of the system. It says, "I don't know who owns this, it could be you!"
A shared_ptr doesn't mean "I don't know who owns this". It means "We own this." Just because one entity does not have exclusive ownership does not mean that anyone can own it.
The purpose of a shared_ptr is to ensure that the pointer cannot be destroyed until everyone who shares it is in agreement that it ought to be destroyed.
Is there such a pointer/patten already in stl/boost that I'm missing, or should I just roll my own?
You could use a shared_ptr exactly the same way you use a scoped_ptr. Just because it can be shared doesn't mean you have to share it. That would be the easiest way to work; just make single-ownership a convention rather than an API-established rule.
However, if you need a pointer that is single-owner and yet has weak pointers, there isn't one in Boost.
I'm not sure that weak pointers would help that much. Typically, if a
component X uses another component Y, X must be informed of Y's demise,
not just to nullify the pointer, but perhaps to remove it from a list,
or to change its mode of operation so that it no longer needs the
object. Many years ago, when I first started C++, there was a flurry of
activity trying to find a good generic solution. (The problem was
called relationship management back then.) As far as I know, no good
generic solution was every found; at least, every project I've worked on
has used a hand built solution based on the Observer pattern.
I did have a ManagedPtr on my site, when it was still up, which behaved
about like what you describe. In practice, except for the particular
case which led to it, I never found a real use for it, because
notification was always needed. It's not hard to implement, however;
the managed object derives from a ManagedObject class, and gets all of
the pointers (ManagedPtr, and not raw pointers) it hands out from it.
The pointer itself is registered with the ManagedObject class, and the
destructor of the ManagedObject class visits them all, and "disconnects"
them by setting the actual pointer to null. And of course, ManagedPtr
has an isValid function so that the client code can test before
dereferencing. This works well (regardless of how the object is
managed—most of my entity objects "own" themselves, and do a
delete this is response to some specific input), except that you tend
to leak invalid ManagedPtr (e.g. whenever the client keeps the pointer
in a container of some sort, because it may have more than one), and
clients still aren't notified if they need to take some action when your
object dies.
If you happen to be using QT, QPointer is basically a weak pointer to a QObject. It connects itself to the "I just got destroyed" event in the pointed-to value, and invalidates itself automatically as needed. That's a seriously hefty library to pull in for what amounts to bug tracking, though, if you aren't already jumping through QT's hoops.
Observer *o = New Observer();
Subject *s = new Subject() ;
s->register(o);
//Is it a good practice to delete the observer in the unregister function?
//I feel it is not. As the Observer object might still be in use, for example ,
//it might be registered to another Subject.
s->unregister(o);
//So it is safe to rely on the client code to delete the object or rely on the smart pointer things
delete o;
I want to confirm whether my above understanding is correct regarding who should delete the observer object.
I agree with your observation. It is not a good practice to delete the observer in the unregister function - for the simple fact that "one who creates the resource must be responsible for deleting the resource"
This will avoid
Magic behavior as perceived by the creator.
Code behavior will be well defined - one who creates must delete. Which will lay overall foundation of understanding of development for new developers to your system.
Similar topic are discussed under lengths in all books with different nomenclature.
I would say use smart pointers as no need to remember to call the delete explictly.
From a design point of view it should be superfluous (while not wrong) to unregister the subjects, if the observer is well implemented. Relying on external code for a behaviour to be robust if it can be enforced can always be considered as poor design.
Regarding the use of smart pointers, if you need the control on the destruction point for some reason (close files at a given point in time for example to avoid access problems in later code) then you should delete explicitly, otherwise it is far more comfortable to rely on smart pointers. That is why there are existing.
As the Subject did not allocate the Observer, it should not attempt to deallocate it. This allows the client of Subject to manage the lifetime and allocation strategy of Observers in any way it chooses (custom allocator, statically allocated, automatic variable). It doesn't force the client to use new.
Obviously it is still to clients responsibility not to allow the Observer to be destroyed before it is "unregistered".
E.g.
Observer o;
Subject s;
s.register(&o); // could take a reference
// ...
s.unregister(&o);
// No potential for forgotten deletes
It depends on your design. I personally prefer that deleting the Observer will automatically disassociate it with the subject, i.e deregister itself in the destructor. That saves the need to bother to deregister, which would require you to have references to both the Subject and the Observer at the point of destruction.
Smartpointer or client code (do not transfer ownership if possible)
If client code has created the object let the same code to destroy it :)
Another argument against deleting is what the Subject object communicates.
By deleting the object your Subject object has taken ownership of the object, as it controls its lifetime. As a raw pointer is passed into the object, and not an auto_ptr or an unique_ptr I would assume as a user of Subject that it does not take ownership of the object without looking at the code. So I would say that the interface of Subject does not communicate that it takes ownership of the object. So Subject should not delete it, because someone else (probably) has ownership of it.
In general, you should avoid side effects like deleting the pointer to an object in a container, unless the container is responsible for creating the pointer as well.
The problems of pointers with the Observer pattern runs a bit deeper than this as well.
An Observer inherently has a reference of some kind to the Subject. If that reference is a direct reference (e.g. not a handle), then if that object goes out of scope or gets deleted, when the Observer makes a Notify(...) call, it will throw an exception (or worse). So you must ensure you Detach(...) from the observer when you delete the Subject.
Forgetting to do this is a problem, so I like the idea of building it into the base class of the virtual destructor. This also means that the Subject has knowledge of the Observer (a reference to it) so it can call Detach(...). Which puts you into a similar situation with the Observer (i.e. if it gets deleted). The approach I have found simplest to use is to have the Observer actually be a singleton with Subjects registering for particular notifications, not just "I have some state for you to update". This is consistent with the GoF Page 298, item 7, "Specifying modifications of interest explicitly". Also, just plain makes sense to narrow the field on updates a bit. It also allows hooking up any Subject form anywhere easier.
Another case to consider is when the Subject is deleted during your Notify(..) iteration. In your Observer, you have a list of Subjects, A, B, and C. You change state and call Notify(...) on A. A deletes B. Now you move on to call Notify(...) on B, which does not exist. If you had it Detach(...) in the destructor, B may not be on the list any more. But it might still if you chose to iterate over a copy of the Subjects you started with instead of the actual list (been there, done that). Your Observer needs to handle a Detach(...) call during iteration for a Notify(...) for this reason.
I have a worked out example of this posted on a blog here.
I'm writing a piece of sotware that needs objects that exchange messages between each other.
The messages have to have the following contents:
Peer *srcPeer;
const char* msgText;
void* payload;
int payLoadLen;
now, Peer has to be a pointer as I have another class that manages Peers. For the rest I'm doubtful... for example I may copy the message text and payload (by allocating two new buffers) as the message is created, then putting the deletes in the destructor of the message. This has the great advantage of avoiding to forget the deletes in the consumer functions (not the mention to make those functions simpler) but it will result in many allocations & copies and can make everything slow. So I may just assing pointers and still have the destructor delete eveything... or ... well this is a common situation that in other programming languages is not even a dilemma as there is a GC. What are your suggestions and what are the most popular practices?
Edit:
I mean that I'd like to know what are the best practices to pass the contents... like having another object that keeps track of them, or maybe shared pointers... or what would you do...
You need clear ownership: when a message is passed between peers, is the ownership changed? If you switch ownership, just have the receiver do the clean-up.
If you just "lease" a message, make sure to have a "return to owner" procedure.
Is the message shared? Then you probably need some copying or have mutexes to protect access.
If all of the messages are similar, consider using a trash stack (http://library.gnome.org/devel/glib/stable/glib-Trash-Stacks.html) - this way, you can keep a stack of allocated-yet-uninitialized message structures that you can reuse without taking the constant malloc/free hit.
Consider using shared_ptr<>, available from Boost and also part of the std::tr1 library, rather than raw pointers. It's not the best thing to use in all cases, but it looks like you want to keep things simple and it's very good at that. It's local reference-count garbage collection.
There are no rules or even best practices for this in C++, except insofar as you make a design decision about pointer ownership and stick to it.
You can try to enforce a particular policy through use of smart pointers, or you can simply document the designed behavior and hope everyone reads the manual.
In C++, you can have reference counting too, like here:
http://library.gnome.org/devel/glibmm/stable/classGlib_1_1RefPtr.html
In this case, you can pass Glib::RefPtr objects. When the last of these RefPtr-s are destroyed associated to a pointer, the object is deleted itself.
If you do not want to use glibmm, you can implement it too, it's not too difficult. Also, probably STL and boost have something like these too.
Just watch out for circular references.
The simplest thing to do is to use objects to manage the buffers. For instance, you might use std::string for both the msgText and payload members and you could do away with the payLoadLen as it would be taken care of by the payload.size() method.
If and only if you measure the performance of this solution and the act of copying the msgText and payload were causing an unacceptable performance hit, you might choose to using a shared pointer to structure that was shared by copies of the message.
In (almost) no situation would I rely on remembering to call delete in a destructor or manually writing safe copy-assignment operator and copy constructor.
The simplest policy to deal with is copying the entire message (deep copy) and send that copy to the recipient. It will require more allocation, but it frees you from many problems related to concurrent access to data. If performance gets critical, there is still room for some optimizations (like avoiding copies if the object only has one owner who is willing to give up ownership of it when sending it, etc).
Each owner is then responsible for cleaning up the message object.