The following is a sketch of how I might have some form of automated memory management in C++:
template<class T>
class Ptr{
public:
/* Some memory management stuff (ref counting etc.)
as Ptr object is initialized */
Ptr( ... ) { .. }
/* Manage reference counts etc.
as Ptr object is copied -- might be necessary
when Ptr is passed to or returned from functions */
Ptr<T>& operator=( .. ) { .. };
/* Do memory management stuff
when this "Pointer" object is destroyed. */
~Ptr() { .. }
private:
/* Pointer to main object */
T* object;
}
class Obj{
public:
static Ptr<Obj> newObj( .. ) { return Ptr<Obj>( new Obj( .. ) ); }
private:
/* Hide constructor so it can only be created by newObj */
Obj( .. ) { .. }
/* some variables for memory management routines */
int refcnt;
..
}
This way, the end-user never has to call new or malloc, and can instead call Obj.newObj( .. ).
However, I'm pretty stumped on how I might do something similar for C.
It doesn't have to be exactly like above, but I don't want to have to care about memory management when it isn't important.
The biggest issue I feel I have is that when a variable in C goes out of scope, I don't really have a 'destructor' that can be signaled to let me know that the variable has gone out of scope.
Yes, that is the primary benefit of C++. You can create classes, which encapsulate functionality. And this functionality can include constructors and destructors to ensure that data is created, managed, and destroyed in a controlled manner.
There is no such option in C unless you implement an entire framework that supports such an option.
For a complete solution and answer to your question see GObject.
Related
I have a native class:
class NativeClass
{
int someVariable;
public:
void someNativeFunction(){}
};
I have a managed class, which lightly wraps this native class.
class ManagedClass
{
NativeClass *nativeClassObject;
public:
void someManagedFunction()
{
nativeClassObject->someNativeFunction();
}
};
I use this managed class in my C# application:
static void Main(string[] args)
{
ManagedClass objManagedClass = new ManagedClass();
objManagedClass.someManagedFunction();//line_1
//At this point onwards objManagedClass still has a reference on the stack, but is not used again.
//So, GC can delete this object.
}
Since objManagedClass is not referenced after line_1, garbage collector is free to destroy the object, even if it is processing the internal native call. This will lead to destruction of objManagedClass, which will in turn destroy *nativeClassObject. This is only likely to happen if someNativeFunction is allocating a lot of memory or is taking a long time, but just to be sure, I must add a reference to objManagedClass later after the call.
class ManagedClass
{
NativeClass *nativeClassObject;
public:
void someManagedFunction()
{
nativeClassObject->someNativeFunction();
...
...
System::GC::KeepAlive(this);
}
};
KeepAlive() call should prevent GC from destroying it. Is there any way I can test this scenario? Some test case I could write that would fail if I did not provide KeepAlive(), but would pass once I called it? Would Thread.Sleep(5000) call in between the managed function help?
You can force garbage collection to start by calling GC::Collect and then wait until garbage collection is finished using GC::WaitForPendingFinalizers. This should allow you to test your scenarios.
Take a look at the example on MSDN
I need to change a state. Then do stuff. Then reset the state back to what it was - e.g:
auto oldActivationOrder = mdiArea->activationOrder();
mdiArea->setActivationOrder( QMdiArea::StackingOrder );
mdiArea->cascadeSubWindows();
mdiArea->setActivationOrder( oldActivationOrder );
How do I do this in a RAII way?
(c++ 11 and/or 14)
Edit: Thanks for all the answers.
There are several suggestions to create a custom class for handling the state change (BoBTFish, mindriot, Mattias Johansson). This solution seems good and clear. However I think it is a drawback that it increases the line count from 4 to 20+. If used a lot this would bloat the code. Also it seems that some locality is lost by having a separate class.
Ami Tavory suggests using std::unique_ptr. This does not have the code bloat issue and maintains locality. However, as Ami also indicates, it may not be the most readable solution.
sp2danny suggests a generalized state-change class that can be reused. This avoids code bloat provided that it can replace several custom classes. I'm going to accept this answer - but I guess the right approach really depends on the context.
RAII: Resource Acquisition Is Initialisation.
Which also implies that Resource Release Is Destruction, although I've never seen people talk about RRID, even though that's the more useful side of it. (Perhaps that should be Termination, or Finalisation?)
The point is, you do some work in the constructor of an object, and effectively reverse it in the destructor. This means that the cleanup is carried out no matter how you exit the scope: multiple returns, multiple breaks, throw an exception, ... (even goto!)
class ScopedActivationOrderChange {
QMdiArea& area_; // the object to operate on
QMdiArea::WindowOrder oldOrder_; // save the old state
public:
ScopedActivationOrderChange(QMdiArea& area, ActivationOrder newOrder)
: area_(area)
, oldOrder_(area_.activationOrder()) // save old state
{
area_.setActivationOrder(newOrder); // set new state
}
~ScopedActivationOrderChange()
{
area_.setActivationOrder(oldOrder_); // reset to old state
}
};
// ...
{ // <-- new scope, just to establish lifetime of the change
ScopedActivationOrderChange orderChange{*mdiArea, QMdiArea::StackingOrder};
mdiArea->cascadeSubWindows();
} // <-- end of scope, change is reversed
The Standard Library doesn't provide any general facility for this. It does provide some for more specific uses, such as std::unique_ptr for deleting dynamically allocated objects, which can in some cases be used for other things, though it's a bit ugly. std::vector can be seen as a RAII class for dynamic arrays, providing some other management facilities also, but this one is less easily abused for other purposes.
Perhaps the most succinct way (albeit possibly not the most readable) of implementing the scoped guard pattern is to use a std::unique_ptr with a custom deleter:
#include <memory>
#include <utility>
int main()
{
void *p, *q;
auto reverser = [&p, &q](char *){std::swap(p, q);};
/* This guard doesn't really release memory -
it just calls the lambda at exit. */
auto guard = std::unique_ptr<char, decltype(reverser)>{nullptr, reverser};
std::swap(p, q);
}
You can do it like this:
class SetActivationOrder
{
public:
SetActivationOrder(QMdiArea *mdiArea, QMdiArea::WindowOrder order)
: m_mdiArea(mdiArea),
m_oldActivationOrder(mdiArea->activationOrder())
{
m_mdiArea->setActivationOrder(order);
}
~SetActivationOrder()
{
m_mdiArea->setActivationOrder(m_oldActivationOrder)
}
private:
QMdiArea *m_mdiArea;
QMdiArea::WindowOrder m_oldActivationOrder;
};
And then use it like this:
{
// This sets the order:
SetActivationOrder sao(mdiArea, QMdiArea::StackingOrder);
mdiArea->cascadeSubWindows();
// Destructor is called at end of scope and sets the old order
}
With RAII (Resource Allocation Is Initialization) you would create an instance of a storage class in the local scope (i.e. on the stack). You pass the state you want to store into the constructor of the storage object and make sure that the destructor of the storage object restores the state again. Because C++ guarantees that the destructor of an object on the local scope will be automatically called for you when the object goes out of scope, also if an exception is thrown, you don't have to worry about remembering to restore the state again.
I would write the class like this:
class ActivationOrderState
{
public:
ActivationOrderState(QMdiArea& area)
: m_area(area)
{
// Get the old value
m_oldOrder = area.activationOrder();
}
~ActivationOrderState()
{
// Restore the old value
m_area.setActivationOrder( m_oldOrder );
}
private:
QMdiArea& m_area;
QMdiArea::WindowOrder m_oldOrder;
};
This object is then used like this
{
ActivationOrderState state(*mdiArea); // saves the state
mdiArea->setActivationOrder( QMdiArea::StackingOrder ); // set the new state
// do other things here...
} // end of scope, destructor is called and state is restored again
to be sure that no other user misuses this code by allocating it on the free store/heap instead of on the local scope, you can delete the operator new:
class ActivationOrderState
{
public:
ActivationOrderState(QMdiArea& area)
: m_area(area)
{
// Get the old value
m_oldOrder = area.activationOrder();
}
~ActivationOrderState()
{
// Restore the old value
m_area.setActivationOrder( m_oldOrder );
}
// Remove the possibility to create this object on the free store.
template<typename... Args> void* operator new(std::size_t,Args...) = delete;
private:
QMdiArea& m_area;
QMdiArea::WindowOrder m_oldOrder;
};
See also
Using RAII to raise thread priority temporarily
You can do a generic template:
template< typename Obj, typename Getter, typename Setter , typename StateType >
class ScopedStateChangeType
{
public:
ScopedStateChangeType( Obj& o, Getter g, Setter s, const StateType& state )
: o(o), s(s)
{
oldstate = (o.*g)();
(o.*s)(state);
}
Obj* operator -> () { return &o; }
~ScopedStateChangeType()
{
(o.*s)(oldstate);
}
private:
Obj& o;
Setter s;
StateType oldstate;
};
template< typename Obj, typename Getter, typename Setter , typename StateType >
auto MakeScopedStateChanger( Obj& o, Getter g, Setter s, StateType state )
-> ScopedStateChangeType<Obj,Getter,Setter,StateType>
{
return { o, g, s, state };
}
use it like:
QMdiArea mdiArea;
{
auto ref = MakeScopedStateChanger(
mdiArea, &QMdiArea::activationOrder, &QMdiArea::setActivationOrder,
QMdiArea::StackingOrder );
ref->cascadeSubWindows();
}
maybe it's worth it if you use this pattern often
How do I use the Poco::ObjectPool class in my c++ program ? Can anyone please delineate this with an example since I am using Poco libraries for the first time.
Thanking in anticipation.
The documentation is pretty clear on this. Actually, all I wrote below I deducted from the docs, I've never used Poco myself... but here goes.
Let's assume you have a class Foo. For some reason you don't want to create a new one every time you need it. Perhaps it is expensive to create. Perhaps it marshals some important resource. You want to pool it, take an object from the pool, and put it back into the pool when you're done with it.
You create an Poco::ObjectPool for Foo objects, giving its starting capacity (number of objects initially created) and peak capacity.
Poco::ObjectPool< Foo > pool( 10, 20 );
You can now "borrow" objects from the pool. Note that the function can return nullptr if the peak capacity is reached.
Foo * f = pool.borrowObject();
...and return it to the pool when done.
pool.returnObject( f );
You can provide a policy class to ObjectPool to customize its behaviour, the interface being defined by PoolableObjectFactory. This class handles how objects are created, activated, validated (to check if they can be reused or need to be destroyed), deactivated, and destroyed (if they cannot be reused, or the pool gets destroyed).
struct FooFactory
{
Foo * createObject() { return new Foo( 42 ); }
void activateObject( Foo * p ) { p.init(); }
bool validateObject( Foo * p ) { return true; }
void deactivateObject( Foo * p ) { p.deinit(); }
void destroyObject( Foo * p ) { delete p; }
};
Poco::ObjectPool< Foo, Foo *, FooFactory > 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.
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.