Set of shared_ptr and set function count - c++

I have a set of shared pointers.
I want to make a function that checks if a shared pointer exists in it.
I assumed I need to use set.count to get it.
But I get 0 all the time... even though the shared pointer exists in there.
So my question is: how does count compare shared pointers?
Please bare in mind I am new to C++, I can provide with code, but there's a lot of it.
EDIT 2:
The function that checks the building and adds a car.
void Garage::addCar(Car& n, Building& m){
shared_ptr<Building> mm(new Building(m));
if (this->Buildings.count(mm) == 0){
cout << m.name << " doesn't exist in " << this->name << "." << endl;
return;
}
shared_ptr<Car> s(new Car(n));
m.addCar(s);
Cars.insert(s);
}
Function that creates Buildings
Building Garage::create Building(string name){
shared_ptr< Building> f_ptr(new Building(name));
Buildings.insert(f_ptr);
return (*f_ptr);
}
Class garage
class Garage {
public:
Garage(string name);
~Garage();
void admitCar(Car& n, Building& m);
void dismissCar(Car& n, Building& m);
void employEmployee(Employee& n, Building& m);
void dismissEmployee(Employee& n, Building& m);
Building createBuilding(string name);
void deleteBuilding(Building&);
private:
int nextIndex;
string name;
set<shared_ptr<Building> > Buildings;
set<shared_ptr<Employee> > Employees;
set<shared_ptr<Car> > Car;
}
Whenever I want to add a car to a building, it says that that building doesnt exist in that garage...
SOLUTION(my own):
bool Garage::hasBuilding(shared_ptr<Building> f){
return (this->Buildings.count(f) != 0);
}
This is the function I created. It works.
I tried Jonathan Wakely and LiKao ways but they were a bit too complicated for me and I had problems which again I couldn't myself solve.
Thank You for the help :)

The pointers you are comparing are different, because they are pointing to different objects. Whenever you say new Building a new building will be created, although it my have the same name as an older building. Hence any pointer to that new Building will be different to any pointer to the old Building from which the new one was created. Hence the comparison is correct, the new Building is not present in the set (you just created it by copying so it cannot be present).
You want a set, which can be compared based on a property of the object the pointer points to. For this you need to add a different comparison function which looks into the pointer to the object. Something like this should work:
struct less_building : std::binary_function<std::shared_ptr<Building>,std::shared_ptr<Building>,bool> {
bool operator()( const std::shared_ptr<Building> & b1, const std::shared_ptr<Building> & b2 ) {
return std::less( b1->name, b2->name );
}
};
This may need some friends declaration depending on your definition of Building, but in general something like this will do the trick.
NOTE1:
Be sure to understand the implications of this, before you use this trick. Using this comparator will mean, that no two Buildings in your set can have the same name, irregardless of any other attribute they may have. Each pair of Buildings which have the same name will afterwards be considered the same Building. Depending on your modelling domain, this may or may not be what you want.
In case you want to also compare other attributes in case the names are the same, then you have to add this to your comparison functor. However then that means that there can be no two Buildings which have the same set of attributes. Again, this may or may not be what you want, depending on the problem.
NOTE2:
Usually it is very inconvenient, to mix std::shared_ptr and references to the same types of objects, which also leads to the problem you are experiences. If you are using std::shared_ptr for a type at any place, you should try to be consistent and only pass these std::shared_ptr around. The reason is, that converting from a std::shared_ptr to a reference (for example using operator*()) is much like a one-way function. I.e. you can get the reference from a std::shared_ptr but it is very hard to get back the std::shared_ptr from the reference. I can think of two ways to get back the std::shared_ptr once you decayed it to a reference, but one requires you to change the object (deriving from std::enable_shared_from_this<Building>) and the other just smells very badly of unclean code (creating a new std::shared_ptr with a no-op deleter to the address of the reference). So I would not recommend either ways.
Instead either choose a design which fits your problem domain, as shown above. Or keep the std::shared_ptr from decaying. If you pass them around as (const)-references to the std::shared_ptr this will not actually cost much more than just passing around the pointer itself.

Based on your "edit 2", I think I see your misunderstanding. These are two completely unrelated shared pointers:
Building m;
shared_ptr<Building> a(new Building(m));
shared_ptr<Building> b(new Building(m));
They will not match inside a std::set.
However, these are related pointers:
Building m;
shared_ptr<Building> a(new Building(m));
shared_ptr<Building> b = a;
So they will match inside a std::set.
Essentially, the comparisons are performed on the pointers, not on the underlying objects.

To answer your question
how does count compare shared pointers?
The comparison is done using the std::shared_ptr's get() method, meaning the managed pointers are compared. Conserning std::set<std::shared_ptr<T>>, the relevant comparison is bool operator<.
See here for more information.

I want to make a function that checks if a shared pointer exists in it.
I don't think you do.
shared_ptr<Building> mm(new Building(m));
if (this->Buildings.count(mm) == 0){
How can the shared pointer mm exist in the set when you've just created it there, and it points to a brand new object you've just created? How could they have got in the set between you creating them and looking for them in the set?
I think you want to check if a Building exists in it, by comparing the building's values, you don't care if a specific object or a specific shared pointer is in the set.
You could either search the set, comparing m to the building pointed to by every element:
void Garage::addCar(Car& n, Building& m){
bool found = false;
for (auto& shptr : Buildings)
{
if (*sp == m) // dereference shared_ptr to compare the Building
{
found = true;
break;
}
}
or use a custom comparison in the set, as in this answer.

Related

Converting "handle" to void*, how to create and store? When to delete?

Introduction
I have created a poll data structure for a game engine, as explained in:-
http://experilous.com/1/blog/post/dense-dynamic-arrays-with-stable-handles-part-1
In short, the structure stores values, instead of pointers.
Here is a draft.
template<class T> class Handle{
int id;
}
template<class T> class PackArray{
std::vector <int>indirection ; //promote indirection here
std::vector <T>data;
//... some fields for pooling (for recycling instance of T)
Handle<T> create(){
data.push_back(T());
//.... update indirection ...
return Id( .... index , usually = indirection.size()-1 .... )
}
T* get(Handle<T> id){
return &data[indirection[id.id]];
//the return result is not stable, caller can't hold it very long
}
//... others function e.g. destroy(Id<T>) ...
}
Problem
Most steps of the refactor to adopt this new data structure are simple, e.g.
Bullet* bullet= new Bullet(); //old version
Handle<Bullet> bullet= packBulletArray.create(); //new version
The problem start when it come to some interfaces the require pointer.
As an example, one of the interfaces is the physic engine.
If I want the engine's collision callback, physic engines likes Box2D and Bullet Physics requires me to pass void*.
Bullet* bullet= .... ;
physicBody->setUserData(bullet); <-- It requires void*.
Question: How should I change the second line to a valid code?
Handle<Bullet> bullet = .... ;
physicBody->setUserData( ???? );
Caution:
(1) There is no guarantee that this instance of "Handle" will exist in the future.
physicBody->setUserData( &bullet ); //can't do this
//e.g. "Handle<Bullet> bullet" in the above code is a local variable, it will be deleted soon
(2) There is no guarantee that the underlying object of "bullet" will exist in the same address in the future.
physicBody->setUserData( bullet->get() ); //can't do this
//because "std::vector<T> data" may reallocate in the future
The answer can assume that:
(1) "physicBody" is encapsulated by me already. It can cache generic pointers if requires, but caching a value of Handle is not allowed, because it creates a severe coupling.
(2) "bullet" has a way to access the correct "physicBody" via its encapsulator. "physicBody" is always deleted before "bullet".
(3) "Handle" also cache "PackArray*", this cache is always a correct pointer.
I guess the solution is something about unique-pointer / make_pointer, but I don't have enough experience to use them for this problem.
P.S. I care about performance.
For reference, this is a sequel of a question create dense dynamic array (array of value) as library that has been solved.

Alternatives to an Object Pool?

I'm not quite sure that I need an object pool, yet it seems the most viable solution, but has some un-wanted cons associated with it. I am making a game, where entities are stored within an object pool. These entities are not allocated directly with new, instead a std::deque handles the memory for them.
This is what my object pool more or less looks like:
struct Pool
{
Pool()
: _pool(DEFAULT_SIZE)
{}
Entity* create()
{
if(!_destroyedEntitiesIndicies.empty())
{
_nextIndex = _destroyedEntitiesIndicies.front();
_destroyedEntitiesIndicies.pop();
}
Entity* entity = &_pool[_nextIndex];
entity->id = _nextIndex;
return entity;
}
void destroy(Entity* x)
{
_destroyedEntitiesIndicies.emplace(x->id);
x->id = 0;
}
private:
std::deque<Entity> _pool;
std::queue<int> _destroyedEntitiesIndicies;
int _nextIndex = 0;
};
If I destroy an entity, it's ID will be added to the _destroyedEntitiesIndicies queue, which will make it so that the ID will be re-used, and lastly it's ID will be set to 0. Now the only pitfall to this is, if I destroy an entity and then immediately create a new one, the Entity that was previously destroyed will be updated to be the same entity that was just created.
i.e.
Entity* object1 = pool.create(); // create an object
pool.destroy(object1); // destroy it
Entity* object2 = pool.create(); // create another object
// now object1 will be the same as object2
std::cout << (object1 == object2) << '\n'; // this will print out 1
This doesn't seem right to me. How do I avoid this? Obviously the above will probably not happen (as I'll delay object destruction until the next frame). But this may cause some disturbance whilst saving entity states to a file, or something along those lines.
EDIT:
Let's say I did NULL entities to destroy them. What if I was able to get an Entity from the pool, or store a copy of a pointer to the actual entity? How would I NULL all the other duplicate entities when destroyed?
i.e.
Pool pool;
Entity* entity = pool.create();
Entity* theSameEntity = pool.get(entity->getId());
pool.destroy(entity);
// now entity == nullptr, but theSameEntity still points to the original entity
If you want an Entity instance only to be reachable via create, you will have to hide the get function (which did not exist in your original code anyway :) ).
I think adding this kind of security to your game is quite a bit of an overkill but if you really need a mechanism to control access to certain parts in memory, I would consider returning something like a handle or a weak pointer instead of a raw pointer. This weak pointer would contain an index on a vector/map (that you store somewhere unreachable to anything but that weak pointer), which in turn contains the actual Entity pointer, and a small hash value indicating whether the weak pointer is still valid or not.
Here's a bit of code so you see what I mean:
struct WeakEntityPtr; // Forward declaration.
struct WeakRefIndex { unsigned int m_index; unsigned int m_hash; }; // Small helper struct.
class Entity {
friend struct WeakEntityPtr;
private:
static std::vector< Entity* > s_weakTable( 100 );
static std::vector< char > s_hashTable( 100 );
static WeakRefIndex findFreeWeakRefIndex(); // find next free index and change the hash value in the hashTable at that index
struct WeakEntityPtr {
private:
WeakRefIndex m_refIndex;
public:
inline Entity* get() {
Entity* result = nullptr;
// Check if the weak pointer is still valid by comparing the hash values.
if ( m_refIndex.m_hash == Entity::s_hashTable[ m_refIndex.m_index ] )
{
result = WeakReferenced< T >::s_weakTable[ m_refIndex.m_index ];
}
return result;
}
}
This is not a complete example though (you will have to take care of proper (copy) constructors, assignment operations etc etc...) but it should give you the idea what I am talking about.
However, I want to stress that I still think a simple pool is sufficient for what you are trying to do in that context. You will have to make the rest of your code to play nicely with the entities so they don't reuse objects that they're not supposed to reuse, but I think that is easier done and can be maintained more clearly than the whole handle/weak pointer story above.
This question seems to have various parts. Let's see:
(...) If I destroy an entity and then immediately create a new one,
the Entity that was previously destroyed will be updated to be the
same entity that was just created. This doesn't seem right to me. How
do I avoid this?
You could modify this method:
void destroy(Entity* x)
{
_destroyedEntitiesIndicies.emplace(x->id);
x->id = 0;
}
To be:
void destroy(Entity *&x)
{
_destroyedEntitiesIndicies.emplace(x->id);
x->id = 0;
x = NULL;
}
This way, you will avoid the specific problem you are experiencing. However, it won't solve the whole problem, you can always have copies which are not going to be updated to NULL.
Another way is yo use auto_ptr<> (in C++'98, unique_ptr<> in C++-11), which guarantee that their inner pointer will be set to NULL when released. If you combine this with the overloading of operators new and delete in your Entity class (see below), you can have a quite powerful mechanism. There are some variations, such as shared_ptr<>, in the new version of the standard, C++-11, which can be also useful to you. Your specific example:
auto_ptr<Entity> object1( new Entity ); // calls pool.create()
object1.release(); // calls pool.destroy, if needed
auto_ptr<Entity> object2( new Entity ); // create another object
// now object1 will NOT be the same as object2
std::cout << (object1.get() == object2.get()) << '\n'; // this will print out 0
You have various possible sources of information, such as the cplusplus.com, wikipedia, and a very interesting article from Herb Shutter.
Alternatives to an Object Pool?
Object pools are created in order to avoid continuous memory manipulation, which is expensive, in those situations in which the maximum number of objects is known. There are not alternatives to an object pool that I can think of for your case, I think you are trying the correct design. However, If you have a lot of creations and destructions, maybe the best approach is not an object pool. It is impossible to say without experimenting, and measuring times.
About the implementation, there are various options.
In the first place, it is not clear whether you're experiencing performance advantages by avoiding memory allocation, since you are using _destroyedEntitiesIndicies (you are anyway potentially allocating memory each time you destroy an object). You'll have to experiment with your code if this is giving you enough performance gain in contrast to plain allocation. You can try to remove _destroyedEntitiesIndicies altogether, and try to find an empty slot only when you are running out of them (_nextIndice >= DEFAULT_SIZE ). Another thing to try is discard the memory wasted in those free slots and allocate another chunk (DEFAULT_SIZE) instead.
Again, it all depends of the real use you are experiencing. The only way to find out is experimenting and measuring.
Finally, remember that you can modify class Entity in order to transparently support the object pool or not. A benefit of this is that you can experiment whether it is a really better approach or not.
class Entity {
public:
// more things...
void * operator new(size_t size)
{
return pool.create();
}
void operator delete(void * entity)
{
}
private:
Pool pool;
};
Hope this helps.

Handling 'units' in an RTS game - c++

I'm currently in the process of making a simple RTS style game in c++.
What i'm wondering is how to handle the creation of new units in the game (ie. making marines from the barrack). How would i store these units?
I was thinking of having a class 'unit' which would then be inherited by specific unit types (ie. marines, firebats, etc) but if i create an array for these (ie. Marines myMarines[20]) that will create a hard cap on these units.
How do i create such an array that can be expanded at will?
Thank you!
The standard library provides them std::vector template for dynamically resizable arrays. A std::vector<Marine> would be the most straightforward alternative to Marines myMarines[20].
However, you probably don't want a separate list for each unit type. It is highly likely that you will want to store all units in the same list, regardless of their type. std::vector<Unit> would sound like the obvious solution but it is not. The problem is that std::vector stores the objects by value. The following would not work right:
std::vector<Unit> v;
v.push_back(Marine("John Doe"));
The problem is that the Marine object will be copied into a Unit object, which is what the vector stores. This kind of copy results in a what is known as slicing: all the Marine specific members will be lost, and only those that exist in Unit will be stored.
One solution to this problem is to store pointers in the vector because copying pointers does not change the objects they point to. But that brings other problems. To store pointers, this means you'll need to allocate the objects dynamically. And that means that now you are responsible for destroying those objects manually. That's a tiresome and error-prone task.
The solution is to store in the vector objects that destroy the dynamically allocated objects automatically, instead of pointers. These objects are known as smart pointers. The simplest one that exists in the standard library is std::unique_ptr.
std::vector<std::unique_ptr<Unit>> v;
v.emplace_back(new Marine("John Doe"));
This is a C++11 feature. If your compiler doesn't support it you can find alternatives in the Boost libraries. Boost even includes a container that acts pretty much like a std::vector of std::unique_ptrs: boost::ptr_vector. That would be another alternative.
You will probably benefit from using an std::vector here. This will allow you to add and remove items at will, and handles dynamic memory allocation internally (without concerning you over the nitty-gritty details!).
Say you want to store a list of marines (denoted by an imaginary class CMarine in the following example):
std::vector<CMarine> marinesList;
Now to add a marine simply do this:
marinesList.push_back( CMarine( <whatever-its-constructor-takes> ) );
To access this marine you can do something like this:
CMarine& marine = marinesList.at( 0 );
marine.someVar = 33;
marine.doMethod();
(I use a reference since CMarine could very well be too bulky to pass around by value efficiently)
You can also loop through all the marines with an iterator like so:
for ( std::vector<CMarine>::iterator _it = marinesList.begin();
_it != marinesList.end(); ++_it );
{
CMarine& marine = *_it;
// Now you can do something with this marine reference
}
UPDATE:
If CMarine is polymorphic, that is, it inherits from a superclass (maybe something like CUnit in your case), and you have a 'global' vector of all units - Georg Fritzsche rightly noted that object slicing could occur (if we are storing by value). Instead you might be better off with a vector of CUnit (smart) pointers like this:
std::vector<std::unique_ptr<CUnit>> unitsList;
// To add a marine:
unitsList.push_back( new CMarine( <whatever-its-constructor-takes> ) );
Read more about vectors here.
Chances are that you don't want a separate container for each of your unit types. Therefore, you'll have to generalise a little and either use something like component based design. Once you have that in place, you'll want an std::vector<GameUnit*> or std::list<GameUnit*> in the first case, and an std::vector<GameUnit> or std::list<GameUnit> in the second case. Either way, you should be using a standard library container to store things.
You can find more information on std::vector and std::list on http://cppreference.com, although your book should already cover them. Also, see
First off, I'd create a Unit class and then subclass your units from it, so you don't have to process a bunch of separate lists. Then, I'd store pointers to the units in:
std::list< Unit * > unitList
A list lets you append however many objects you like, and, while it doesn't allow for rapid access to random members of the list, you can iterate through it easily and not have to worry about it trying to move large amounts of memory around when you delete something out of the middle of it.
One thing I like to do is have a unit register itself with the units list automatically from inside the unit's constructor. So assuming Marine is a subclass of Unit, all I would need to do would be to say:
new Marine(x_pos, y_pos);
...and a new Marine would be created and appended to the list automatically.
At this point, each frame, you can iterate through every Unit in unitList and run the unit's update function (which is a virtual function that is different for each subclass).
After the update loop, run a cleanup loop that iterates through unitsList again, finds all destroyed units, and removes them from the list and deletes them.
I say std::vector ! I usually create a base class of unit (or GameObject as I like to call them) Here's what I would have done:
class GameObject {} // Maybe has virtual methods for the Size, Location and Image?
class Barrack
{
std::vector< GameObject > gameUnits;
public:
// code
void AddUnit() { gameUnits.push_back( GameObject() ); }
void DestroyUnit(int index);
// etc. etc.
}
However, if you don't want to rely too much on inheritance, i.e you have different kinds of units and all of them don't inherit from one base class, you may try this vector_any class I implemented some days ago to hold the sprites of my RPG game:
struct element
{
element( void* data, const std::type_info& info ) : value(data), type( &info ) {}
void* value;
const std::type_info* type;
};
class type_conversion_exception : exception {};
class linked_vector
{
vector< element > stack;
public:
linked_vector() {}
template< typename T > void add_item( T& item )
{
stack.push_back( element( static_cast< void* >( &item ), typeid(item) ) );
}
template< typename T > T& get_item( int index )
{
if ( *( stack[index].type ) == typeid( T ) )
{
return *( static_cast< T* >( stack[index].value ) );
}
else throw type_conversion_exception();
}
};
You can use it for your game units like this.
linked_vector gameUnits;
MilitaryUnit mUnit;
AirUnit aUnit;
gameUnits.add_item( mUnit );
gameUnits.add_item( aUnit );
try{ draw( gameUnits.get_item< MilitaryUnit >(0) ); }
catch( type_conversion_exception e ) { /* error handling */ }
// etc. etc.
The choice between vector and list is a tricky one. Every time you push_back() on the vector, the whole vector is reallocated and copied. A list doesn't have this issue. Neverthless, you could preallocated the vector and have a unit cap - this is fine unless you want effectively 'unlimited' units on a map, but you probably don't.
As for lookup, the vector has constant time lookup for any index, but how often would you want to jump to a particular index? When it comes to iterating over a whole list or vector I don't think there's any performance difference.
Also, when you want to remove a Unit (when it's killed) from a vector you would have some more reallocate and shuffle issues, a list can remove any item much more efficiently.
I'm personally leaning towards a list.
And as already stated the container you choose should hold pointers to the unit base class.

Pointer Reference Pattern - Common use?

In a system where current object is operated by other contained objects, when reference to current object is passed, it appears that the link goes on and on....without any end ( For the code below, Car->myCurrentComponent->myCar_Brake->myCurrentComponent->myCar_Brake->myCurrentComponent ....).
ICar and Car->myCurrentComponent->myCar_Brake refer to same address, point to same objects. It's like Car contains Brake which refers to Car.
In fact, Car is the only object, myCar_Brake and myCar_Speed just refer(point) to it.Is this kind of use of reference and pointer normal? Are there any potential problem with this approach?
Sample Code
class Brake
class C
class Car
{
public:
Car();
// Objects of type B and C.
Brake* myBrake;
Speed* mySpeed;
// Current component under action.
Component* myCurrentComponent;
}
/******************************/
// Constructor
Car::Car()
{
myBrake = new Brake(*this);
mySpeed = new Speed(*this);
myCurrentComponent = myBrake;
}
/******************************/
class Brake: public Component
{
public:
Brake(Car&);
// Needs to operate on A.
Car* myCar_Brake;
}
// Constructor
Brake::Brake(Car&)
{
myCar_Brake = Car;
}
/******************************/
class Speed
{
public:
Speed(Car&);
// Needs to operate on A.
Car* myCar_Speed;
}
// Constructor
Speed::Speed(Car&)
{
myCar_Speed = Car;
}
/****************************/
There's no fundamental problem with having circular references in your object graph, so long as you understand that and don't try to traverse your object graph without keeping track of which objects you've encountered. To specifically answer your question, having circular references between objects is relatively common; it's the way a doubly-linked list works, for example.
Although, as Paul mentions, there is no problem with having circular references, the above code example is totally missing encapsulation and is not memory leak safe.
Does it make sense to allow something like this?
Speed::Speed(Car& value)
{
myCar_Speed = value;
// WTF code below
value->myCurrentComponent->myCar_Brake = NULL;
}
Also,
Car::Car()
{
myBrake = new Brake(*this);
mySpeed = new Speed(*this);
//if Speed::Speed(Car&) throws an exception, memory allocated for myBrake will leak
myCurrentComponent = myBrake;
}
Never use raw pointers without some kind of a resource manager.
Without debating the validity of the actual object structure of the relation of Car, Break and Speed, this approach has one minor problem: it can be in invalid states.
If - something - goes wrong, it is possible in this setup, that a Car instance#1 has a Break instance#2 that belongs to a Car instance#3. A general problem with doubly-linked lists too - the architecture itself enables invalid states. Of course careful visibility modifier choosing and good implementation of functions can guarantee it will not happen. And when its done and safe, you stop modifying it, take it as a 'black box', and just use it, thus eliminating the probability of screwing it up.
But, I'd personally recommend to avoid architectures that allow invalid states for high level, constantly maintained code. A doubly-linked list is a low level balck box code that will most likely not need any code changes, like ever. Can you say that about your Car, Break and Speed?
If a Car had a Break and Speed, and Break and Speed would not know of their "owning Car", it would be impossible to make and invalid state. Of course, it might not suit the concrete situation.

Manually incrementing and decrementing a boost::shared_ptr?

Is there a way to manually increment and decrement the count of a shared_ptr in C++?
The problem that I am trying to solve is as follows. I am writing a library in C++ but the interface has to be in pure C. Internally, I would like to use shared_ptr to simplify memory management while preserving the ability to pass a raw pointer through the C interface.
When I pass a raw pointer through the interface, I would like to increment the reference count. The client will then be responsible to call a function that will decrement the reference count when it no longer needs the passed object.
Maybe you are using boost::shared_ptr accross DLL boundaries, what won't work properly. In this case boost::intrusive_ptr might help you out. This is a common case of misuse of shared_ptr people try to work around with dirty hacks... Maybe I am wrong in your case but there should be no good reason to do what you try to do ;-)
ADDED 07/2010: The issues seem to come more from DLL loading/unloading than from the shared_ptr itself. Even the boost rationale doesn't tell much about the cases when boost::intrusive_ptr should be preferred over shared_ptr. I switched to .NET development and didn't follow the details of TR1 regarding this topic, so beware this answer might not be valid anymore now...
In your suggestion
The client will then be responsible to decrement the counter.
means that the client in question is responsible for memory management, and that your trust her. I still do not understand why.
It is not possible to actually modify the shared_ptr counter... (hum, I'll explain at the end how to...) but there are other solutions.
Solution 1: complete ownership to the client
Hand over the pointer to the client (shared_ptr::release) and expect it to pass the ownership back to you when calling back (or simply deleting the object if it is not really shared).
That's actually the traditional approach when dealing with raw pointers and it apply here as well. The downside is that you actually release ownership for this shared_ptr only. If the object is actually shared that might prove inconvenient... so bear with me.
Solution 2: with a callback
This solution means that you always keep ownership and are responsible to maintain this object alive (and kicking) for as long as the client needs it. When the client is done with the object, you expect her to tell you so and invoke a callback in your code that will perform the necessary cleanup.
struct Object;
class Pool // may be a singleton, may be synchronized for multi-thread usage
{
public:
int accept(boost::shared_ptr<Object>); // adds ptr to the map, returns NEW id
void release(int id) { m_objects.erase(id); }
private:
std::map< int, boost::shared_ptr<Object> > m_objects;
}; // class Pool
This way, your client 'decrementing' the counter is actually your client calling a callback method with the id you used, and you deleting one shared_ptr :)
Hacking boost::shared_ptr
As I said it is possible (since we are in C++) to actually hack into the shared_ptr. There are even several ways to do it.
The best way (and easiest) is simply to copy the file down under another name (my_shared_ptr ?) and then:
change the include guards
include the real shared_ptr at the beginning
rename any instance of shared_ptr with your own name (and change the private to public to access the attributes)
remove all the stuff that is already defined in the real file to avoid clashes
This way you easily obtain a shared_ptr of your own, for which you can access the count. It does not solve the problem of having the C code directly accessing the counter though, you may have to 'simplify' the code here to replace it by a built-in (which works if you are not multi-threaded, and is downright disastrous if you are).
I purposely left out the 'reinterpret_cast' trick and the pointer offsets ones. There are just so many ways to gain illegit access to something in C/C++!
May I advise you NOT to use the hacks though? The two solutions I presented above should be enough to tackle your problem.
You should do separation of concerns here: if the client passes in a raw pointer, the client will be responsible for memory management (i.e. clean up afterwards). If you create the pointers, you will be responsible for memory management. This will also help you with the DLL boundary issues that were mentioned in another answer.
1. A handle?
If you want maximum security, gives the user a handle, not the pointer. This way, there's no way he will try to free it and half-succeed.
I'll assume below that, for simplicity's sake, you'll give the user the object pointer.
2. acquire and unacquire ?
You should create a manager class, as described by Matthieu M. in his answer, to memorize what was acquired/unacquired by the user.
As the inferface is C, you can't expect him to use delete or whatever. So, a header like:
#ifndef MY_STRUCT_H
#define MY_STRUCT_H
#ifdef __cplusplus
extern "C"
{
#endif // __cplusplus
typedef struct MyStructDef{} MyStruct ; // dummy declaration, to help
// the compiler not mix types
MyStruct * MyStruct_new() ;
size_t MyStruct_getSomeValue(MyStruct * p) ;
void MyStruct_delete(MyStruct * p) ;
#ifdef __cplusplus
}
#endif // __cplusplus
#endif // MY_STRUCT_H
Will enable the user to use your class. I used a declaration of a dummy struct because I want to help the C user by not imposing him the use of the generic void * pointer. But using void * is still a good thing.
The C++ source implementing the feature would be:
#include "MyClass.hpp"
#include "MyStruct.h"
MyManager g_oManager ; // object managing the shared instances
// of your class
extern "C"
{
MyStruct * MyStruct_new()
{
MyClass * pMyClass = g_oManager.createMyClass() ;
MyStruct * pMyStruct = reinterpret_cast<MyStruct *>(pMyClass) ;
return pMyStruct ;
}
size_t MyStruct_getSomeValue(MyStruct * p)
{
MyClass * pMyClass = reinterpret_cast<MyClass *>(p) ;
if(g_oManager.isMyClassExisting(pMyClass))
{
return pMyClass->getSomeValue() ;
}
else
{
// Oops... the user made a mistake
// Handle it the way you want...
}
return 0 ;
}
void MyStruct_delete(MyStruct * p)
{
MyClass * pMyClass = reinterpret_cast<MyClass *>(p) ;
g_oManager.destroyMyClass(pMyClass) ;
}
}
Note that the pointer to MyStruct is plain invalid. You should not use it for whatever reason without reinterpret_cast-ing it into its original MyClass type (see Jaif's answer for more info on that. The C user will use it only with the associated MyStruct_* functions.
Note too that this code verify the class does exist. This could be overkill, but it is a possible use of a manager (see below)
3. About the manager
The manager will hold, as suggested by Matthieu M., a map containing the shared pointer as a value (and the pointer itself, or the handle, as the key). Or a multimap, if it is possible for the user to somehow acquire the same object multiple times.
The good thing about the use of a manager will be that your C++ code will be able to trace which objects were not "unacquired" correctly by the user (adding info in the acquire/unacquire methods like __FILE__ and __LINE__ could help narrow the bug search).
Thus the manager will be able to:
NOT free a non-existing object (how did the C user managed to acquire one, by the way ?)
KNOW at the end of execution which objects were not unaquired
In case of unacquired objets, destroy them anyway (which is good from a RAII viewpoint)
This is somewhat evil, but you could offer this
As shown in the code above, it could even help detect a pointer does not point to a valid class
I came across a use case where I did need something like this, related to IOCompletionPorts and concurrency concerns. The hacky but standards compliant method is to lawyer it as described by Herb Sutter here.
The following code snippet is for std::shared_ptr as implemented by VC11:
Impl File:
namespace {
struct HackClass {
std::_Ref_count_base *_extracted;
};
}
template<>
template<>
void std::_Ptr_base<[YourType]>::_Reset<HackClass>(std::auto_ptr<HackClass> &&h) {
h->_extracted = _Rep; // Reference counter pointer
}
std::_Ref_count_base *get_ref_counter(const std::shared_ptr<[YourType]> &p) {
HackClass hck;
std::auto_ptr<HackClass> aHck(&hck);
const_cast<std::shared_ptr<[YourType]>&>(p)._Reset(std::move(aHck));
auto ret = hck._extracted; // The ref counter for the shared pointer
// passed in to the function
aHck.release(); // We don't want the auto_ptr to call delete because
// the pointer that it is owning was initialized on the stack
return ret;
}
void increment_shared_count(std::shared_ptr<[YourType]> &sp) {
get_ref_counter(sp)->_Incref();
}
void decrement_shared_count(std::shared_ptr<[YourType]> &sp) {
get_ref_counter(sp)->_Decref();
}
Replace [YourType] with the type of object you need to modify the count on. It is important to note that this is pretty hacky, and uses platform specific object names. The amount of work you have to go through to get this functionality is probably indicative of how bad of an idea it is. Also, I am playing games with the auto_ptr because the function I am hijacking from shared_ptr takes in an auto_ptr.
Another option would be to just allocate dynamically a copy of the shared_ptr, in order to increment the refcount, and deallocate it in order to decrement it. This guarantees that my shared object will not be destroyed while in use by the C api client.
In the following code snippet, I use increment() and decrement() in order to control a shared_ptr. For the simplicity of this example, I store the initial shared_ptr in a global variable.
#include <iostream>
#include <boost/shared_ptr.hpp>
#include <boost/make_shared.hpp>
#include <boost/scoped_ptr.hpp>
using namespace std;
typedef boost::shared_ptr<int> MySharedPtr;
MySharedPtr ptr = boost::make_shared<int>(123);
void* increment()
{
// copy constructor called
return new MySharedPtr(ptr);
}
void decrement( void* x)
{
boost::scoped_ptr< MySharedPtr > myPtr( reinterpret_cast< MySharedPtr* >(x) );
}
int main()
{
cout << ptr.use_count() << endl;
void* x = increment();
cout << ptr.use_count() << endl;
decrement(x);
cout << ptr.use_count() << endl;
return 0;
}
Output:
1
2
1
fastest possible concurrent lockless manager (if you know what you are doing).
template< class T >
class shared_pool
{
public:
typedef T value_type;
typedef shared_ptr< value_type > value_ptr;
typedef value_ptr* lock_handle;
shared_pool( size_t maxSize ):
_poolStore( maxSize )
{}
// returns nullptr if there is no place in vector, which cannot be resized without locking due to concurrency
lock_handle try_acquire( const value_ptr& lockPtr ) {
static value_ptr nullPtr( nullptr );
for( auto& poolItem: _poolStore ) {
if( std::atomic_compare_exchange_strong( &poolItem, &nullPtr, lockPtr ) ) {
return &poolItem;
}
}
return nullptr;
}
lock_handle acquire( const value_ptr& lockPtr ) {
lock_handle outID;
while( ( outID = try_acquire( lockPtr ) ) == nullptr ) {
mt::sheduler::yield_passive(); // ::SleepEx( 1, false );
}
return outID;
}
value_ptr release( const lock_handle& lockID ) {
value_ptr lockPtr( nullptr );
std::swap( *lockID, lockPtr);
return lockPtr;
}
protected:
vector< value_ptr > _poolStore;
};
std::map is not so fast, requires additional search, extra memory, spin-locking.
But it grants extra safety with handles approach.
BTW, hack with manual release/acquire seems to be a much better approach (in terms of speed and memory usage). C++ std better add such a functionality in their classes, just to keep C++ razor-shaped.