Home » U++ Library support » U++ Core » Ptr improve
| Ptr improve [message #32403] |
Mon, 16 May 2011 14:07  |
|
|
Hello Mirek,
I propose to improve a little Ptr class by add autodelete in PteBase::Prec and Autodelete in PteBase:
in h file:
template <class T> class Ptr;
class PteBase {
protected:
struct Prec {
PteBase *ptr;
Atomic n;
bool autodelete;
};
volatile Prec *prec;
Prec *PtrAdd();
void Autodelete();
static void PtrRelease(Prec *prec);
static Prec *PtrAdd(const Uuid& uuid);
static void Lock();
static void Unlock();
PteBase();
~PteBase();
friend class PtrBase;
};
class PtrBase {
protected:
PteBase::Prec *prec;
void Set(PteBase *p);
virtual void Release();
void Assign(PteBase *p);
public:
virtual ~PtrBase();
};
template <class T>
class Pte : public PteBase {
friend class Ptr<T>;
};
template <class T>
class PteAuto : public PteBase {
friend class Ptr<T>;
public:
PteAuto(){PteBase::Autodelete();}
};
template <class T>
class Ptr : public PtrBase, Moveable< Ptr<T> > {
T *Get() const { return prec&&prec->ptr ? static_cast<T *>(prec->ptr) : NULL; }
protected:
void Release();
void Autodelete();
public:
T *operator->() const { return Get(); }
T *operator~() const { return Get(); }
operator T*() const { return Get(); }
Ptr& operator=(T *ptr) { Assign(ptr); return *this; }
Ptr& operator=(const Ptr& ptr) { Assign(ptr.Get()); return *this; }
Ptr() { prec = NULL; }
Ptr(T *ptr) { Set(ptr); }
Ptr(const Ptr& ptr) { Set(ptr.Get()); }
~Ptr() { Autodelete(); }
String ToString() const;
friend bool operator==(const Ptr& a, const T *b) { return a.Get() == b; }
friend bool operator==(const T *a, const Ptr& b) { return a == b.Get(); }
friend bool operator==(const Ptr& a, const Ptr& b) { return a.prec == b.prec; }
friend bool operator==(const Ptr& a, T *b) { return a.Get() == b; }
friend bool operator==(T *a, const Ptr& b) { return a == b.Get(); }
friend bool operator!=(const Ptr& a, const T *b) { return a.Get() != b; }
friend bool operator!=(const T *a, const Ptr& b) { return a != b.Get(); }
friend bool operator!=(const Ptr& a, const Ptr& b) { return a.prec != b.prec; }
friend bool operator!=(const Ptr& a, T *b) { return a.Get() != b; }
friend bool operator!=(T *a, const Ptr& b) { return a != b.Get(); }
};
template<class T>
void Ptr<T>::Release(){
Autodelete();
PtrBase::Release();
}
template<class T>
void Ptr<T>::Autodelete(){
PteBase::Lock();
if(prec&&prec->autodelete&&prec->ptr&&prec->n < 2){
delete (T*)(prec->ptr);
prec->ptr = NULL;
}
PteBase::Unlock();
}
template <class T>
String Ptr<T>::ToString() const{
return prec&&prec->ptr ? FormatPtr(Get()) : String("0x0");
}
in cpp:
#include "Core.h"
NAMESPACE_UPP
static StaticCriticalSection sPteLock;
void PteBase::Lock(){
sPteLock.Enter();
}
void PteBase::Unlock(){
sPteLock.Leave();
}
PteBase::Prec *PteBase::PtrAdd(){
sPteLock.Enter();
if(prec) {
++prec->n;
sPteLock.Leave();
}
else {
sPteLock.Leave();
prec = new Prec;
prec->n = 1;
prec->ptr = this;
prec->autodelete = false;
}
return const_cast<Prec *>(prec);
}
void PteBase::PtrRelease(Prec *prec){
CriticalSection::Lock __(sPteLock);
if(prec && --prec->n == 0){
if(prec->ptr){
prec->ptr->prec = NULL;
}
delete prec;
prec = NULL;
}
}
void PteBase::Autodelete(){
if(!prec){
prec = new Prec;
prec->n = 0;
prec->ptr = this;
}
prec->autodelete = true;
}
PteBase::PteBase(){
prec = NULL;
}
PteBase::~PteBase(){
CriticalSection::Lock __(sPteLock);
if(prec)
prec->ptr = NULL;
}
void PtrBase::Release(){
PteBase::PtrRelease(prec);
}
void PtrBase::Set(PteBase *p){
prec = p ? p->PtrAdd() : NULL;
}
void PtrBase::Assign(PteBase *p){
Release();
Set(p);
}
PtrBase::~PtrBase(){
Release();
}
END_UPP_NAMESPACE
and a little test:
#include <Core/Core.h>
using namespace Upp;
struct Foo : PteAuto<Foo> {
String text;
};
Foo* factory(){
return new Foo;
}
CONSOLE_APP_MAIN
{
Ptr<Foo> ptr;
{
Ptr<Foo> ptr1 = new Foo;
ptr1->text = "Text";
ptr = ptr1;
Cout() << (void*)~ptr << " -> " << ptr->text << "\n";
}
Cout() << "-------------\n";
Cout() << (void*)~ptr << "\n";
ptr = factory();
ptr = factory();
}
To use this PteAuto you need to know exactly that classes which use this class will automatically deleted.
Any comments are welcome!
PS: changed the realization to resolve with destructor of T.
[Updated on: Mon, 16 May 2011 15:38] Report message to a moderator
|
|
|
|
|
|
| Re: Ptr improve [message #32405 is a reply to message #32404] |
Mon, 16 May 2011 15:31   |
|
|
| mirek wrote on Mon, 16 May 2011 16:05 |
| Quote: | Any comments are welcome!
|
No. This is going against U++ principles.
Mirek
|
Exists situations when you do not know when to delete the created objects. In this case prec->n will counting and delete the unused objects. PteAuto can be use only with new constructor.
This can be as a future.
Or maybe exist something like?
[Updated on: Mon, 16 May 2011 15:36] Report message to a moderator
|
|
|
|
| Re: Ptr improve [message #32406 is a reply to message #32404] |
Mon, 16 May 2011 16:06   |
|
|
| mirek wrote on Mon, 16 May 2011 16:05 |
| Quote: | Any comments are welcome!
|
No. This is going against U++ principles.
Mirek
|
Mirek,
As an alternative solution can you add a new virtual method OnPrecDelete() in class PteBase:
class PteBase {
protected:
struct Prec {
PteBase *ptr;
Atomic n;
};
virtual void OnPrecDelete() {};
volatile Prec *prec;
Prec *PtrAdd();
static void PtrRelease(Prec *prec);
static Prec *PtrAdd(const Uuid& uuid);
PteBase();
~PteBase();
friend class PtrBase;
};
and change in cpp file the method:
void PteBase::PtrRelease(Prec *prec){
CriticalSection::Lock __(sPteLock);
if(prec && --prec->n == 0){
if(prec->ptr){
prec->ptr->prec = NULL;
prec->ptr->OnPrecDelete();
}
delete prec;
prec = NULL;
}
}
In this case I can use for my specialized class this functionality by:
#include <Core/Core.h>
using namespace Upp;
struct Foo : public Pte<Foo> {
String text;
~Foo();
protected:
virtual void OnPrecDelete(){delete (Foo*)this;}
};
Foo::~Foo(){
Cout() << "deleted " << (void*)(this) << "\n";
}
Foo* factory(){
return new Foo;
}
CONSOLE_APP_MAIN
{
Ptr<Foo> ptr;
{
Ptr<Foo> ptr1 = new Foo;
ptr1->text = "Text";
ptr = ptr1;
Cout() << (void*)~ptr << " -> " << ptr->text << "\n";
}
Cout() << "-------------\n";
Cout() << (void*)~ptr << "\n";
ptr = factory();
ptr = factory();
}
|
|
|
|
|
|
| Re: Ptr improve [message #32446 is a reply to message #32408] |
Wed, 18 May 2011 11:40   |
 |
kohait00
Messages: 939 Registered: July 2009 Location: Germany
|
Experienced Contributor |
|
|
for this matter
http://www.cplusplus.com/reference/std/memory/auto_ptr/
http://www.boost.org/doc/libs/1_46_1/libs/smart_ptr/smart_pt r.htm
std::auto_ptr -> UPP::One<>, sole ownership, not shared amongst others, pick semantic
| Quote: |
Conceptually, smart pointers are seen as owning the object pointed to, and thus responsible for deletion of the object when it is no longer needed.
The smart pointer library provides six smart pointer class templates:
scoped_ptr <boost/scoped_ptr.hpp> Simple sole ownership of single objects. Noncopyable.
scoped_array <boost/scoped_array.hpp> Simple sole ownership of arrays. Noncopyable.
shared_ptr <boost/shared_ptr.hpp> Object ownership shared among multiple pointers.
shared_array <boost/shared_array.hpp> Array ownership shared among multiple pointers.
weak_ptr <boost/weak_ptr.hpp> Non-owning observers of an object owned by shared_ptr.
intrusive_ptr <boost/intrusive_ptr.hpp> Shared ownership of objects with an embedded reference count.
These templates are designed to complement the std::auto_ptr template.
|
scoped_ptr is a restricted version of One<>
shared_ptr shares ownership of same object among multiple shared_ptr instances (aka ref count, or Value). for this we dont have a 'clean' leightweight implementations, sth like Shared<> would be great.
weak_ptr is a weak ref, pointing same stuff shared_ptr already points to, comparable to Ptr<>, it doesnt hold ownership, just as Ptr<> doesnt, so we actually *do* have allmost all of it.
maybe we really should consider to implement such a shared ownership container, sth like Shared<>
[Updated on: Wed, 18 May 2011 11:42] Report message to a moderator
|
|
|
|
| Re: Ptr improve [message #32450 is a reply to message #32446] |
Wed, 18 May 2011 13:12   |
|
|
| kohait00 wrote on Wed, 18 May 2011 12:40 |
maybe we really should consider to implement such a shared ownership container, sth like Shared<>
|
Yes,
Shared<>(shared_ptr<>) is the container which I need. I will create this class and propose to vote.
Thank you!
Ion.
[Updated on: Wed, 18 May 2011 13:12] Report message to a moderator
|
|
|
|
| Re: Ptr improve [message #32476 is a reply to message #32450] |
Thu, 19 May 2011 19:09   |
 |
kohait00
Messages: 939 Registered: July 2009 Location: Germany
|
Experienced Contributor |
|
|
here is a proposal..
//shared pointer
//idea borrowed from boost shared_ptr, an additional chunk of memory is managed
//which centrally holds the refcount of that object pointed to
//if Shared is created freshly, it AtomicInc's the ref count to 1;
//if a Shared is destroyed it AtomicDec's the refcount, and if its 0,
// it will delete both, the object and the refcount chunk
//if another instance is created as copy, the refcount is taken and incremented.
//if it is assigned, it decrements own existing counter, possibly releasing mem, and retains new
//pick semantic is not needed here anymore, it not even is possible
//since an 'operator=(const Shared<>&) is needed to aquire the source. pick is const in some cases as well)
//thus Shared is only Moveable, without deepcopyoption, which in fact would speak agains the idea of Shared anyway
//Attach / Detach remains
template <class T>
class Shared : Moveable< Shared<T> > {
mutable T *ptr;
Atomic *rfc;
void Retain() const { ASSERT(rfc); AtomicInc(*rfc); }
void Release() { ASSERT(rfc); if(AtomicDec(*rfc) == 0) { Free(); delete rfc; rfc = NULL; } }
void Free() { if(ptr && ptr != (T*)1) delete ptr; }
void Chk() const { ASSERT(ptr != (T*)1); }
void ChkP() const { Chk(); ASSERT(ptr); }
public:
void Attach(T *data) { Free(); ptr = data; }
T *Detach() pick_ { ChkP(); T *t = ptr; ptr = NULL; return t; }
T *operator-() pick_ { return Detach(); }
void Clear() { Free(); ptr = NULL; }
void operator=(T *data) { Attach(data); }
void operator=(const Shared<T>& d){ Release(); ptr = d.ptr; rfc = d.rfc; Retain(); }
void operator=(pick_ One<T>& d) { Attach(d.Detach()); }
const T *operator->() const { ChkP(); return ptr; }
T *operator->() { ChkP(); return ptr; }
const T *operator~() const { Chk(); return ptr; }
T *operator~() { Chk(); return ptr; }
const T& operator*() const { ChkP(); return *ptr; }
T& operator*() { ChkP(); return *ptr; }
template <class TT>
TT& Create() { TT *q = new TT; Attach(q); return *q; }
T& Create() { T *q = new T; Attach(q); return *q; }
bool IsEmpty() const { Chk(); return !ptr; }
operator bool() const { return ptr; }
Shared() { ptr = NULL; rfc = new Atomic(1); }
Shared(T *newt) { ptr = newt; rfc = new Atomic(1); }
Shared(const Shared<T>& p) { ptr = p.ptr; rfc = p.rfc; Retain(); }
~Shared() { Release(); }
Shared(pick_ One<T>& p) { ptr = p.Detach(); rfc = new Atomic(1); }
Shared(const One<T>& p, int) { ptr = DeepCopyNew(*p); rfc = new Atomic(1); }
};
i first thought deriving from One<> but it will have problems with pick semantics
so i decided to stay with a clean separated version, but it's 80% One<> code
i added a convenience pick semantic for One<>
it's open for discussion..
Shared<Size> Test(Shared<Size> s)
{
if(!s.IsEmpty())
RLOG(*s);
return s;
}
CONSOLE_APP_MAIN
{
Shared<Size> p;
{
Shared<Size> s;
s.Create();
*s = Size(123,456);
Shared<Size> q;
q = Test(s);
p = q;
}
if(!p.IsEmpty())
RLOG(*p);
One<Size> os;
os.Create();
*os = Size(1,2);
p = os;
RLOG(*p);
os.Create();
*os = Size(3,4);
p = Shared<Size>(os);
RLOG(*p);
}
[Updated on: Thu, 19 May 2011 19:15] Report message to a moderator
|
|
|
|
| Re: Ptr improve [message #32481 is a reply to message #32476] |
Fri, 20 May 2011 08:32   |
|
|
| kohait00 wrote on Thu, 19 May 2011 20:09 | here is a proposal..
//shared pointer
//idea borrowed from boost shared_ptr, an additional chunk of memory is managed
//which centrally holds the refcount of that object pointed to
//if Shared is created freshly, it AtomicInc's the ref count to 1;
//if a Shared is destroyed it AtomicDec's the refcount, and if its 0,
// it will delete both, the object and the refcount chunk
//if another instance is created as copy, the refcount is taken and incremented.
//if it is assigned, it decrements own existing counter, possibly releasing mem, and retains new
//pick semantic is not needed here anymore, it not even is possible
//since an 'operator=(const Shared<>&) is needed to aquire the source. pick is const in some cases as well)
//thus Shared is only Moveable, without deepcopyoption, which in fact would speak agains the idea of Shared anyway
//Attach / Detach remains
template <class T>
class Shared : Moveable< Shared<T> > {
mutable T *ptr;
Atomic *rfc;
void Retain() const { ASSERT(rfc); AtomicInc(*rfc); }
void Release() { ASSERT(rfc); if(AtomicDec(*rfc) == 0) { Free(); delete rfc; rfc = NULL; } }
void Free() { if(ptr && ptr != (T*)1) delete ptr; }
void Chk() const { ASSERT(ptr != (T*)1); }
void ChkP() const { Chk(); ASSERT(ptr); }
public:
void Attach(T *data) { Free(); ptr = data; }
T *Detach() pick_ { ChkP(); T *t = ptr; ptr = NULL; return t; }
T *operator-() pick_ { return Detach(); }
void Clear() { Free(); ptr = NULL; }
void operator=(T *data) { Attach(data); }
void operator=(const Shared<T>& d){ Release(); ptr = d.ptr; rfc = d.rfc; Retain(); }
void operator=(pick_ One<T>& d) { Attach(d.Detach()); }
const T *operator->() const { ChkP(); return ptr; }
T *operator->() { ChkP(); return ptr; }
const T *operator~() const { Chk(); return ptr; }
T *operator~() { Chk(); return ptr; }
const T& operator*() const { ChkP(); return *ptr; }
T& operator*() { ChkP(); return *ptr; }
template <class TT>
TT& Create() { TT *q = new TT; Attach(q); return *q; }
T& Create() { T *q = new T; Attach(q); return *q; }
bool IsEmpty() const { Chk(); return !ptr; }
operator bool() const { return ptr; }
Shared() { ptr = NULL; rfc = new Atomic(1); }
Shared(T *newt) { ptr = newt; rfc = new Atomic(1); }
Shared(const Shared<T>& p) { ptr = p.ptr; rfc = p.rfc; Retain(); }
~Shared() { Release(); }
Shared(pick_ One<T>& p) { ptr = p.Detach(); rfc = new Atomic(1); }
Shared(const One<T>& p, int) { ptr = DeepCopyNew(*p); rfc = new Atomic(1); }
};
i first thought deriving from One<> but it will have problems with pick semantics
so i decided to stay with a clean separated version, but it's 80% One<> code
i added a convenience pick semantic for One<>
it's open for discussion..
Shared<Size> Test(Shared<Size> s)
{
if(!s.IsEmpty())
RLOG(*s);
return s;
}
CONSOLE_APP_MAIN
{
Shared<Size> p;
{
Shared<Size> s;
s.Create();
*s = Size(123,456);
Shared<Size> q;
q = Test(s);
p = q;
}
if(!p.IsEmpty())
RLOG(*p);
One<Size> os;
os.Create();
*os = Size(1,2);
p = os;
RLOG(*p);
os.Create();
*os = Size(3,4);
p = Shared<Size>(os);
RLOG(*p);
}
|
Very nice,
I thought deriving from PtrBase, but it conflicts with Ptr<>.
Your proposal seems to be very clear.
|
|
|
|
| Re: Ptr improve [message #32482 is a reply to message #32481] |
Fri, 20 May 2011 11:04   |
 |
kohait00
Messages: 939 Registered: July 2009 Location: Germany
|
Experienced Contributor |
|
|
i am thinking of an addition
class A;
class B : A
think of a Shared<B> that can point to same instance, as some Shared<A> do.. so they need to share the refcount.. so which ever of the Shared instances dies last, will destroy the object properly. provided virtual dtor..
thats a current use case for me now..
in C# this is done automatically, since 'object' has got a ref count internally. with this U++ would come very close to that..
[Updated on: Fri, 20 May 2011 11:07] Report message to a moderator
|
|
|
|
|
|
|
|
|
|
| Re: Ptr improve [message #32488 is a reply to message #32487] |
Fri, 20 May 2011 14:43   |
 |
kohait00
Messages: 939 Registered: July 2009 Location: Germany
|
Experienced Contributor |
|
|
i totally agree with you, thinking the shared or semi-GC way to the end, if it's implemented halfway (like this would be in this case) would bring one in serious trouble sooner or later. you end up breaking your head on how to prevent this damn thing from beeing destroyed. and u keep a Shared<T> instance around to do just that. and you could keep the whole instance just as well.
if at all used, it needs to be veeery consequent. so if one decides to handle an object in shared way, it needs to go completely like that. no mixes of API's (half is using Shared<T> and half T*)..
and it makes trouble when handling a polymorph type, here you want a Shared<Base>, there a Shared<Derived> and they'd need to have the same ref (which i adressed as well, but it's not posted yet)
nevertheless, as a helper, i will put it in my Gen package, as a matter of discussion, just in case one happens to need it some time again. is that ok?
[Updated on: Fri, 20 May 2011 14:45] Report message to a moderator
|
|
|
|
|
|
|
|
|
|
| Re: Ptr improve [message #32522 is a reply to message #32518] |
Mon, 23 May 2011 18:26   |
|
|
The GC in U++ idea is interesting, but I think it will never be the main memory management strategy for U++ It could be optional using e.g. USE_GC flag, which would be (most probably) mutually exclusive with USE_MALLOC. I just wonder if it would really bring enough speed up to justify all the code to be written to make it work
|
|
|
|
| Re: Ptr improve [message #32528 is a reply to message #32516] |
Mon, 23 May 2011 22:37   |
 |
mirek
Messages: 14290 Registered: November 2005
|
Ultimate Member |
|
|
| cbpporter wrote on Mon, 23 May 2011 07:52 | Here is an idea that has been going around in my head for a while: what if we combine the U++ way with GC.
GC is great, but the cost of mark & sweep can be to much for some cases.
Traditional memory management is problematic, and we have a relatively big cost of allocation/deallocation.
|
Well, that is relative, average allocation/deallocation is about pretty fast in U++.... (about the same as link/unlink in double-linked list + a couple of simple loads)
| Quote: |
With the U++ we have everything belongs somewhere.
|
GC is quite incompatible with the concept of destructors.
| Quote: |
But what if we kept the principle intact for non heap allocated objects, but for heap allocated one, the destructor would only mark the object for deletion, and it would actually get deleted latter.
|
IMO results in unmaintainable mess.
Besides, GC AFAIK is still not a part of C++. And you cannot realistically add it by library - the best you can do is stochastic approach (Boehm), which works fine, unless you are processing white noise 
Still, what is unclear to my is why to complicate your code with heap if you do not have to? The whole mission of U++ is to eliminate universal shared heap as much as possible.
Mirek
|
|
|
|
|
|
| Re: Ptr improve [message #32537 is a reply to message #32528] |
Tue, 24 May 2011 09:25   |
cbpporter
Messages: 1428 Registered: September 2007
|
Ultimate Contributor |
|
|
| mirek wrote on Mon, 23 May 2011 23:37 |
| cbpporter wrote on Mon, 23 May 2011 07:52 | Here is an idea that has been going around in my head for a while: what if we combine the U++ way with GC.
GC is great, but the cost of mark & sweep can be to much for some cases.
Traditional memory management is problematic, and we have a relatively big cost of allocation/deallocation.
|
Well, that is relative, average allocation/deallocation is about pretty fast in U++.... (about the same as link/unlink in double-linked list + a couple of simple loads)
| Quote: |
With the U++ we have everything belongs somewhere.
|
GC is quite incompatible with the concept of destructors.
| Quote: |
But what if we kept the principle intact for non heap allocated objects, but for heap allocated one, the destructor would only mark the object for deletion, and it would actually get deleted latter.
|
IMO results in unmaintainable mess.
Besides, GC AFAIK is still not a part of C++. And you cannot realistically add it by library - the best you can do is stochastic approach (Boehm), which works fine, unless you are processing white noise 
Still, what is unclear to my is why to complicate your code with heap if you do not have to? The whole mission of U++ is to eliminate universal shared heap as much as possible.
Mirek
|
Destructors are not generally incompatible with GC, just the normal GC scenarios and implementation we have now. What I am proposing is reversing the order of the GC flow.
Another additional advantage would be that it would eliminate one of the big disadvantages of conservative GC: false positives and inability to deal with extremely large heaps or data that looks like pointers.
With what I am proposing, only objects whose destructors have been called will be collected, or those that were marked by the API. It is not GC, it is the U++ memory management flow, with one single difference: data is not deleted immediately. It is delayed.
This would apply to all containers that allocate memory, so it is not about eliminating universal shared heap or not so it wouldn't contrast with our mission statement.
|
|
|
|
| Re: Ptr improve [message #32553 is a reply to message #32537] |
Tue, 24 May 2011 17:46   |
 |
mirek
Messages: 14290 Registered: November 2005
|
Ultimate Member |
|
|
| cbpporter wrote on Tue, 24 May 2011 03:25 |
| mirek wrote on Mon, 23 May 2011 23:37 |
| cbpporter wrote on Mon, 23 May 2011 07:52 | Here is an idea that has been going around in my head for a while: what if we combine the U++ way with GC.
GC is great, but the cost of mark & sweep can be to much for some cases.
Traditional memory management is problematic, and we have a relatively big cost of allocation/deallocation.
|
Well, that is relative, average allocation/deallocation is about pretty fast in U++.... (about the same as link/unlink in double-linked list + a couple of simple loads)
| Quote: |
With the U++ we have everything belongs somewhere.
|
GC is quite incompatible with the concept of destructors.
| Quote: |
But what if we kept the principle intact for non heap allocated objects, but for heap allocated one, the destructor would only mark the object for deletion, and it would actually get deleted latter.
|
IMO results in unmaintainable mess.
Besides, GC AFAIK is still not a part of C++. And you cannot realistically add it by library - the best you can do is stochastic approach (Boehm), which works fine, unless you are processing white noise 
Still, what is unclear to my is why to complicate your code with heap if you do not have to? The whole mission of U++ is to eliminate universal shared heap as much as possible.
Mirek
|
Destructors are not generally incompatible with GC, just the normal GC scenarios and implementation we have now. What I am proposing is reversing the order of the GC flow.
Another additional advantage would be that it would eliminate one of the big disadvantages of conservative GC: false positives and inability to deal with extremely large heaps or data that looks like pointers.
With what I am proposing, only objects whose destructors have been called will be collected, or those that were marked by the API. It is not GC, it is the U++ memory management flow, with one single difference: data is not deleted immediately. It is delayed.
This would apply to all containers that allocate memory, so it is not about eliminating universal shared heap or not so it wouldn't contrast with our mission statement.
|
Well, very unlikely to happen, but for the fun of theoretical debate:
How do you plan to implement GC? are you going to write your C++ compiler? How would it handle typical C++ inconsistencies like pointer casts
In the past, I was experimenting with such library based GC approach, where only specific objects were subjects of GC. I was able to get it working, and it was quite optimal, however the whole thing collapsed the moment you have started mixing such objects and regular ones. I have not found a way out. Since then I consider the whole point of GC in C++ moot - perhaps Boehm or is good for fixing leaky code, but my conclusion is that you can either have reliable destructors or GC. There is nothing in between.
Mirek
|
|
|
|
|
|
|
|
| Re: Ptr improve [message #32567 is a reply to message #32403] |
Wed, 25 May 2011 09:34   |
mr_ped
Messages: 826 Registered: November 2005 Location: Czech Republic - Praha
|
Experienced Contributor |
|
|
"I am wondering if we could get a best of both worlds"
The problem with me is, that I don't see anything good about GC, except that you can be careless about where are your data.
As most of the SW task is to manipulate data, I don't find that idea attractive at all, I prefer to know exactly what my data do and where they sit and why. From there I never really wished for GC, gives me goosebumps to never know exactly when the memory is freed.
edit:
"What I want is to delay the free operation"
and why?? What's the advantage? I see plenty of problems with it, but no single advantage.
[Updated on: Wed, 25 May 2011 09:36] Report message to a moderator
|
|
|
|
| Re: Ptr improve [message #32569 is a reply to message #32567] |
Wed, 25 May 2011 10:27   |
 |
kohait00
Messages: 939 Registered: July 2009 Location: Germany
|
Experienced Contributor |
|
|
the strong typed nature of C++ and especially U++ leaves you with a lot of control and responsibility. imho constructing object without care (like it is in C#) is both easy and wasting performance, inviting for careless handling with ressources. knowing what's up and needed is best practice to keep apps reactive. beeing that said, i go along with mr_pen & mirek.
this does not mean that Shared<> is just bad per se. it is merley a helper. but seeing it as an invitation to go GC is a bit too far i think. as mirek said, GC is compiler support. either have it or dont. there is no safe way in between.
some more info about shared_ptr usage, which clearly shows that it brings a lot of hassle as well. hassle one can spare when investing the thinking power in a correct model. a lot of work to save work is cumbersome.
http://www.codeproject.com/KB/stl/boostsmartptr.aspx#Example : Using shared_ptr in containers
[Updated on: Wed, 25 May 2011 10:28] Report message to a moderator
|
|
|
|
|
|
|
|
|
|
|
|
Goto Forum:
Current Time: Sun Apr 26 10:10:05 GMT+2 2026
Total time taken to generate the page: 0.01330 seconds
|