First, my actual question
I have a shared pointer in a map, I want to remove that shared pointer from the map when there are no other references besides the shared pointer in the map itself, so the target gets released. How can I do this? Alternatively, what's a better design to solve my problem?
Background below:
Out of nostalgia I've been writing a MUD engine in C++ using a MySQL backend. I'm at the point now of persisting entities (things like accounts, characters and so forth in this context). I'm having a bit of trouble figuring out the best way to implement this and decided to seek some advice.
My current persistence architecture looks like this, taking character for an example
Character entity -> Character storage -> Character persistence -> MySQL
Character entity refers to the character itself and is analogous to a model in MVC. It doesn't have anything but data and only knows about other entities.
Character storage is a container currently responsible for holding instances of the character entity in memory. When a request is made to find a character either by ID or name, it checks it's memory, implemented as a map of std::string containing UUIDs to a std::shared_ptr. If we have an instance already in memory, we pass back a shared pointer, if not, we ask the persistence layer for it, store it in the map and then pass a shared pointer back to it.
The persistence layer is abstract, there's a character_persistence interface which has a concrete implementation of mysql_character_persistence, so I could easily switch to different forms of persistence.
I used reference counting and a templated entity_ptr type.
I created a entity_ptr_provider interface which defined the methods obtain(uuid) and release(uuid). An entity_ptr takes a templated argument of entity type (account, character etc), an entity of that type and an entity_ptr_provider.
On construction or copy of the entity_ptr type, it calls obtain on the entity_ptr_provider with the UUID of the entity so it can increment the references to it, when it's deconstructed, it calls release which allows the entity_ptr_provider to decrement the reference. When references reach 0, it's released from the table.
Related
I have a collection of objects, some of which reference others. The referencing is implemented using pointers, however pointers do not persist between application runs - the data structures are serialized and deserialized, but each time their memory addresses of the actual objects are different.
I have implemented a hash table, using integer ids as keys and pointers as values, storing the ids and using them to lookup the object pointer for each id. Sometimes references to objects are created before the actual referenced object is created, so in such cases I have to implement a check for this id, and inform the objects, referencing that id the moment an object with such id is created.
It works, but I feel like it is clumsy and inefficient. So my question is whether there is established design pattern to deal with this problem.
I am attempting to construct a bunch of objects that can share data, but aren't coupled to each other. What I want is for the fields of each object to be a shared_ptr to whatever data they need. Once all the objects are created, this will fulfill all my needs, but my issue is how to distribute the information needed to create the shared_ptr's, since the types can be anything.
I will be creating all objects that share a set of data at once inside a factory object. Also, each shared field will have an enum entry to signify the attribute type (not data type). For instance the enum will have an entry that is Position, and every object that needs position information will use enum to key into a map to find the information it needs to create the shared_ptr.
What I want from my system is this:
Pass an SetEnum to the factory, which defines which "set" of objects to create, along with an optional map<AttributeEnum, ??> that defines the initial data of set of objects
Create the necessary objects, using a map<AttributeEnum, ??> to create shared_ptr's as fields in each of the objects. If the object needs a field corresponding to a specific value of AttributeEnum, it will pull its value from the map. If that value is not a key in the map, it will create it with a default value, and add it to the map for future objects to use. This step can be done during or after construction if a method with a template type would be helpful to solve the issue.
The issue is that I want errors at compile time, not run time. How can I map AttributeEnum to a type? For example, every field corresponding to an AttributeEnum value of Position will have type shared_ptr<double>, but I want a compile error if I attempt to associate Position with, for instance, shared_ptr<int>. My question is how to go about this?
A couple different systems I have thought of (albeit none of them ensure the errors at compile time):
Pass around a std::map<Enum, shared_ptr<void> > and static cast the shared_ptr's to the appropriate types.
Construct the objects, then iterate through the Enum, checking each object for which attributes it needs, then passing the proper pointers to it.
Having one object "own" each attribute, and force the other to get the information via a message-passing system.
I am considering storing two parallel sets of data, the AttributeEnum having entry Position, and compiler constants that would define the types such as #define POSITION double, then I would simply use POSITION for the type where ever I must, but this would make the code much harder to read.
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.
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.
I'm writing a game and an accompanying engine in C++. The engine relies heavily on automation using a simple embedded scripting language. Scripts can create object classes, define event listeners on them, and produce instances from them. At present, an instance must be bound to a script-global identifier in order to preserve its existence. The obvious result of this is that there can be no anonymous objects, which will be by far the most common.
At present, instances are managed using a std::set<Instance*, spatial_sort>, where spatial_sort is a functor that sorts instances by position, for rendering and collision detection. Instances are removed and re-inserted each frame using their current position as a hint, under the assumption that they're not likely to move a whole lot in a fiftieth of a second. If a dead flag is set in the instance, it is erased from the set. The Instance constructors and destructor invoke insert(this) and erase(this), respectively.
In order to allow anonymous instances, I want to change the set to a std::set<boost::shared_ptr<Instance>, spatial_sort>, which would allow Instance to share ownership of instances and preserve their existence until they destroy themselves. Unfortunately, because the calls to insert() need to be placed in the constructor, shared_from_this() won't work for obtaining a shared_ptr to the Instance. It doesn't matter at all that Instance happens to already inherit from boost::enable_shared_from_this<> via its base class.
Can anyone recommend a suitable workaround?
Edit:
I did what I should have been doing in the first place, and split the behaviour of the Instance class into two classes: Instance and Reference. The expression new SomeClass in a script then returns a Reference to a new Instance. The Instance objects themselves are never managed using a shared_ptr, so they are responsible for committing suicide in response to a suitable event, e.g., end of animation, end of level, etc.
Thanks for the help! Refactoring is as good a solution as any if it Just Works.
You could add a static method to Instance that you then use to create new objects and that also does the administrative stuff like adding it to the set:
static Instance* create(int something) {
boost::shared_ptr<Instance> sptr(new Instance(something));
instanceset.insert(sptr);
return sptr.get();
}
If you want to make this the only way to construct an object of this class you could also make the normal constructor private or protected.
For more on this see also the C++ FAQ Lite entry about "Dynamic binding during initialization", which is not directly related but uses the same technique to work around the restrictions on the use of virtual functions in constructors.