Should I use smart pointers for passing "this" - c++

Coming from mostly C#, I am going through the exercise of understanding how best to manage object ownership in c++, so bear with me.
I have a Bus class which has a method called OpenChannel that returns a Channel object. The Bus keeps a list of channels, because if the Bus is closed, all channels should be closed. If an individual channel is closed, the bus remains open, but the channel should be removed from the Bus open channel list.
The way I planned on handling this was as follows:
std::unique_ptr<Channel> Bus::OpenChannel(int channel_number){
int handle = //call dll to open channel
auto chnl = std::make_unique<Channel>(this, channel_number, handle);
this->open_channels_.push_back(chnl);
}
void Bus::OnChannelClosed(Channel channel){
//remove from open_channels_
}
and then in the channel class, there is a close method
void Channel::Close(){
//make call to dll to close channel
owning_bus_->OnChannelClosed(channel);
}
What I'm wondering is two fold -- first, for the bus being passed to the channel object's constructor, should I just use a regular pointer, or should I use a smart pointer? If a smart pointer, does it make sense to wrap "this" up in one? And two, it doesn't quite sit right with me that the bus has a public OnChannelClosed method that is exposed for any object to call. This could result in the Bus removing the channel due to a call from a non-channel object. I could make the Channel a friend of the Bus class, but my gut feel is there may be a better way.
edit:
based on some responses I figured I'd add more info. "Bus" wraps up a dll which can be initialized and uninitialized (and reinitialized again if required). When it is uninitialized, all open channel handles go invalid per the docs. I am starting to think my library wrapper should have an Initialize, Uninitialize, and "CreateChannel" method which returns a Channel which can then be operated on. Theoretically, I will never be uninitializing the bus while channels are open. But should it happen, I was hoping to gracefully manage that. However, if I'm exposing channel, there is a of course the possibility the channel object being used in another location goes invalid if the bus is uninitialized.
I think that the best way to handle this if possible is not allow the bus to be uninitialized as long as there are open channels. Maybe a shared pointer can be used to manage this? Or maybe channel shouldn't be exposed at all and Bus methods should all take a channel number as an input, and then the calls will be delegated to the correct channel.

With regards to your first question:
What I'm wondering is two fold -- first, for the bus being passed to
the channel object's constructor, should I just use a regular pointer,
or should I use a smart pointer?
Smart pointers are incredibly useful because they remove the need for manual memory tracking. In the example you provided, your Bus class only needs a pointer to a Channel so it can keep track of which Channel instance contains it. In this context, there is no need to use a smart pointer, since all bus instances should be destroyed before the channel that holds them.
And two, it doesn't quite sit right with me that the bus has a public
OnChannelClosed method that is exposed for any object to call.
If all that you're concerned is that no other class other than Bus should be able to invoke the method OnChannelClosed, you can always make Bus a friend class of Channel, and set the method OnChannelClosed as private or protected.
It feels however, that you are trying to manage memory with two different approaches here, though:
1- You want Channel to keep track of all Bus instances, and
2- You want to use smart pointer so you don't need to keep track of memory at all.
One thing I noticed is that Bus::OpenChannel stores a unique_ptr inside a vector, and, (presumably) returns that same unique_ptr as the output of the function. This is not possible. As the name suggests, unique pointers can only be owned by one object. If you need multiple objects to have access to the pointer, you should use a shared_ptr instead.

Related

Should my API functions take shared_ptr or weak_ptr

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.

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.

c++ how to make sure memory is reclaimed via shared pointers

I am using boost shared pointers and these pointers are really shared all over the application. There are conditions, where such a shared pointer becomes invalid. For example, a shared pointer to a network resource, that can become invalid because network became unavailable. In such a scenario, where the shared pointer becomes invalid, i would like all objects to stop using it. How can i send a message to all objects that the pointer is invalid. If it was a normal pointer, i could set it to null and all client code should be checking for null pointer before using it. But, in case of a shared pointer, which keeps reference count, how can i achieve similar functionality ?
You can use weak pointers. That is, the code that handles the network events has the shared_ptr<Res> while everybody else has a weak_ptr<Res>. Now,
when the resource becomes unavailable, just reset the shared_ptr to NULL;
when a client wants to use the resource, call lock() into the weak_ptr and test whether the returned shared_ptr is valid before using.
If it was a normal pointer, i could set it to null and all client code should be checking for null pointer before using it.
I doubt that. You'd then have copies of that raw pointer that point to invalid objects. You'd think that would solve the problem, but it doesn't. It amplifies it.
The fact is that the shared pointer itself doesn't become invalid, the object it contains does. So, logically, whether it's still safe to use it should be contained in the object, not the shared pointer.
a shared pointer to a network resource, that can become invalid because network became unavailable.
Just throw an exception when you attempt to call a method that attempts to use the network...
I would be inclined to follow the pattern used by standard streams: have an object that represents the resource, which can enter an error state and/or throw an exception when it detects (or is informed) that the network is no longer available. If you can't change the existing resource class, then this new object can hold the existing resource object (that currently all your users have shared pointers to), and the users can share the new object.
Unless you need all the users of this resource to respond promptly when it becomes unavailable, there doesn't seem any point trying to propagate a message to them all. If you just want them to stop using it, they can do that the next time they try to use it, and discover that it doesn't work any more. If they do really need a message, then write something to keep a list of them all, and call some function on them when the event that they're interested in occurs. This is called the Observer pattern or "listeners", and armed with those search terms you can find implementations and alternatives.
Ideally, users should be able to check for the error state either as part of using the resource, or immediately afterwards. Testing before use is usually error-prone, since it creates a window in which the network perhaps could become unavailable after the test but before it's used. Once your code has to handle that case correctly you might as well make it the only case, by not bothering to check in advance.
You need to store more information. You could put the resource together with a bool in a tuple, or you could use boost::optional, and set it to none when you want to invalidate it.
You almost certainly shouldn't be using shared pointer for this, since
its semantics don't correspond to what you need. Shared pointer
implements a sort of poor man's garbage collection, where the object
ceases to exist when there are no more pointers to it; you need the
opposite, that the pointers to the object cease to exist when there is
no more object. (A reverse garbage collection, so to speak.)
I've used a ManagedPtr in the past; the pointer registers itself with
the object, which must derive from a ManagingObj class which sets the
pointers to null in its destructor. This works sometimes, but it still
doesn't remove entries from lists, etc. where the other objects may be
keeping it. And in practice, other objects which know about your
network resource object may want to take specific actions when it
disappears. In the end, you almost always need to use the observer
pattern: any object which acquires a pointer to your object registers
with it to be notified in case of its demise.

How can I maintain a weak reference on a COM object in C++?

In my application, I'm hooking various functions for creating COM objects (such as CoCreateInstanceEx) to get notified whenever some object is created. I'm keeping track of all created objects in a std::list and I'm iterating over that list to do various things (like checking which OLE objects have been activated).
The issue with this is that right now, whenever adding an IUnknown pointer to my list, I call IUnknown::AddRef on it to make sure that it doesn't get destroyed while I'm tracking it. That's not what I really want though; the lifetime of the object should be as long (or short) as it is without my tracing code, so I'd rather like to maintain a weak reference on the objects. Whenever the last reference to some tracked COM object is removed (and thus the object gets destroyed), I'd like to get notified so that I can update my bookkeeping (e.g. by setting the pointer in my list to NULL).*
What's the best way to do this? Right now, I'm patching the (first) VTable of all created objects so that the calls to IUnknown::Release via the first vtable get notified. However, this won't work for COM interfaces which inherit from multiple interfaces (and thus have multiple vtables), but I'm not sure whether this is really a problem: given the Rules for Implementing QueryInterface, there should always be just one IUnknown returned by IUnknown::QueryInterface, right? So I could do that and then patch that vtable.
Furthermore, this approach is also a bit hairy since it involves creating thunks which generate some code. I only implemented this for 32bit so far. Not a big issue, but still.
I'm really wondering whether there isn't a more elegant way to have a weak reference to a COM object. Does anybody know?
*: The next thing I'll have to solve is making this work correctly in case I have active iterators (I'm using custom iterator objects) traversing the list of COM objects. I may need to keep track of the active iterators and once the last one finished, remove all null pointers from the list. Or something like that.
This isn't an answer as much as a set of issues why this is a really tricky thing to do - I'm putting it in as an answer since there's too much information here than fits in a comment :)
My understanding is that the concept of weak reference just doesn't exist in COM, period. You've got reference counting via IUnknown, and that's the sum total of how COM deals with object lifetime management. Anything beyond that is, strictly speaking, not COM.
(.Net does support the concept, but it's got an actual GC-based memory manager to provide appropriate support, and can treat WeakRef objects differently than regular references in memory. But that's not the case with the very simple world that COM assumes, which is a world of plain memory and pointers, and little more.)
COM specifies that reference counting is per-interface; any COM object is free to do ref counting per object as a convenience, but the upshot is that if you're wrapping an object, you have to assume the most restrictive case. So you cannot assume that any given IUnknown will be used for all addrefs/releases on that object: you'd really need to track each interface separately.
The canonical IUnknown - the one you get back by QI'ing for IUnknown - could be any interface at all - even a dedicated IUnknown that is used only for the purpose of acting as an identity! - so long as the same binary pointer value is returned each time. All other interfaces could be implemented any way; typically the same value is returned each time, but a COM object could legitimately return a new IFoo each time someone QI's for IFoo. Or even keep around a cache of IFoos and return one at random.
...and then you've got aggregation to deal with - basically, COM doesn't have a strong concept of object at all, it's all about interfaces. Objects, in COM, are just a collection of interfaces that happen to share the same canonical IUnknown: they might be implemented as a single C/C++ object behind the scenes, or as a family of related C/C++ objects presenting a facade of a 'single COM object'.
Having said all of that, given that:
I'm tracing the state of various components (including all COM objects) of this software for the sake of debugging
Here's an alternate approach that might produce some useful data to debug with.
The idea here is that many implementations of COM objects will return the ref count as the return value to Release() - so if they return 0, then that's a clue that the interface may have been released.
This is not guaranteed, however: as MSDN states:
The method returns the new reference count. This value is intended to be used only for test purposes.
(emphasis added.)
But that's apparently what you're doing here.
So one thing you could do, assuming you own the calling code, is to replace calls with Release() with an inline called MyRelease() or similar that will call release, and if it notices that the return value is 0, then notes that the interface pointer is now possibly freed - removes it from a table, logs it to a file, etc.
One major caveat: keep in mind that COM does not have a concept of weak ref, even if you try to hack something together. Using a COM interface pointer that has not been AddRef()'d is illegal as far as COM is concerned; so if you save away interface pointer values in any sort of list, the only thing you should so with those is treat them as opaque numbers for debugging purposes (eg. log them to a file so you can correlate creates with destroys, or keep track of how many you have outstanding), but do not attempt to use them as actual interface pointers.
Again, keep in mind that nothing requires a COM object to follow the convention of returning the refcount; so be aware that you could see something that looks like a bug but is actually just an implementation of Release just happens to always returns 0 (or rand(), if you're especially unlucky!)
First, you're right that QueryInterface for IUnknown should always return the same pointer; IUnknown is treated as the object's identity IIRC, so needs to be stable.
As for weak pointers, off the top of my head, maybe you could give CoMarshalInterThreadInterfaceInStream a whirl? It is meant to allow you to serialize a reference to a COM object into a stream, then create a new reference to the object on some other thread using the stream. However, if you serialise into a stream and retain the stream as a sort of weak pointer, then unmarshal later on to recover the pointer, you could check whether unmarshalling fails; If so, the object is gone.
With WinRT IWeakReference was added to enable weak refs to COM objects. Objects created with WRL's RuntimeClass support IWeakReference by default (can be disabled with an option).
you can use IWeakReference in your designs but it means you will need to use at least some WinRT concepts, IInspectable based interface.

Member variable pointers to COM objects

Is there any problem with keeping member variable pointer refernces to COM objects and reussing the reference through out the class in C++.
Is anybody aware of a reason why you would want to call .CreateInstance every time you wanted a to use the COM object i.e. you were getting a fresh instance each time.
I cannot see any reason who you would want to do this,
Thanks,
(No is an acceptable answer!!!)
It depends on what you really want.
If you need the same object every time you have to keep a pointer to it. If you need a new object every time (for whatever reason) you have to create a new instance each time. If you don't care keeping the object is preferable because calls to CoCreateInstance() are relatively expensive.
There is no general rule in this case because there are a number of variables that decide whether it is a good idea or not.
First: If you own the COM objects in question i.e. have source code and control over how they are used, then yes its perfectly safe.
If COM objects are 3rd party COM objects sometimes crappy code in them may force you to "createInstance" on them every time you use them - out of necessity (and self preservation).
If the COM object is acting as a proxy object you may need to create them every time you use them because of stuff behind the scene i.e. other clients using the same object.
there are more situations, but to summarize: it depends...
I would say it depends on what the COM object is and how you use it. It is generally fine to reuse an ADO connection, but if you leave it in a dirty state then you may encounter odd behavior when you reuse it. Some COM object may have a re-initialize or clear method you can call to reset them back to a clean state.