www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Weak pointers in D

reply Sean Kelly <sean f4.ca> writes:
I'm coming to like the idea of weak pointers in D and have been wondering how
they could be implemented.  The typical smart-pointer approach won't work
without copy semantics for UDTs, which seems to leave either a syntax change (^
as a weak pointer signifier, for example) or perhaps some way to flag something
as a weak pointer to the GC.  The only problem with the GC approach is that it
makes passing  weak pointers to functions somewhat awkward.  I dun't suppose
someone else can suggest an alternate method?


Sean
Oct 15 2005
parent reply Larry Evans <cppljevans cos-internet.com> writes:
On 10/15/2005 11:30 AM, Sean Kelly wrote:
 I'm coming to like the idea of weak pointers in D and have been wondering how
 they could be implemented.  The typical smart-pointer approach won't work
 without copy semantics for UDTs, which seems to leave either a syntax change (^
 as a weak pointer signifier, for example) or perhaps some way to flag something
 as a weak pointer to the GC.  The only problem with the GC approach is that it
 makes passing  weak pointers to functions somewhat awkward.  I dun't suppose
 someone else can suggest an alternate method?

I'm a D newbie but an experienced C++ programmer; so, pardon me if I'm missing something obvious in my following remarks: Why can't a D use policy_ptr's like the boost::shared_ptr and boost::weak_ptr? A policy based garbage collector: policy_gc<SomePolicy> would know which type by using a template member function (does D have these?): template<typename SomePolicyPtr> policy_gc<SomeGcPolicy>::visit_field(SomePolicyPtr& a_ptr) IOW, SomePolicyPtr could be: StrongPtr<SomeReferent> or: WeakPtr<SomeReferent> and policy_gc<SomeGcPolicy::visit_field would behave appropriately.
Oct 15 2005
next sibling parent reply Georg Wrede <georg.wrede nospam.org> writes:
Larry Evans wrote:
 On 10/15/2005 11:30 AM, Sean Kelly wrote:
 
 I'm coming to like the idea of weak pointers in D and have been 
 wondering how they could be implemented.  The typical smart-pointer
 approach won't work without copy semantics for UDTs, which seems to
 leave either a syntax change (^ as a weak pointer signifier, for
 example) or perhaps some way to flag something as a weak pointer to
 the GC.  The only problem with the GC approach is that it makes
 passing  weak pointers to functions somewhat awkward.  I dun't 
 suppose someone else can suggest an alternate method?

I'm a D newbie but an experienced C++ programmer; so, pardon me if I'm missing something obvious in my following remarks: Why can't a D use policy_ptr's like the boost::shared_ptr and boost::weak_ptr? A policy based garbage collector: policy_gc<SomePolicy> would know which type by using a template member function (does D have these?): template<typename SomePolicyPtr> policy_gc<SomeGcPolicy>::visit_field(SomePolicyPtr& a_ptr) IOW, SomePolicyPtr could be: StrongPtr<SomeReferent> or: WeakPtr<SomeReferent> and policy_gc<SomeGcPolicy::visit_field would behave appropriately.

Just off hand, we might implement weak references with just an array of pairs, consisting of a flag and a pointer-to-a-weak-reference. Source would be compiled as it now is, with weak and strong references created just the way strong references are now created. But my new array would contain pointers to the locations where any Weak reference is. We also need another field in GC's Deletables table. This boolean would contain knowledge of whether any weak references point to its area. Running code would not be any different from what it is now. But upon GC time, if a suspected reference is found (as it is done today), the GC checks if it is in my table. If it is, then, instead of marking the Pointed-to-Object as not-deletable, it would turn on the flag in my table, and turn on the ExistWeakPointer in its own Deletables table. At sweep time, any area found deletable but marked as ExistWeakPointer, the GC would go through this my new array, and for every flag found it would check whether the pointer points to a reference that points to the area we are trying to delete. If it is, then the Weak reference (not the pointer-to-a-weak-reference in my table) is zeroed and the tuple flag cleared. Then the rest of the table is checked for possible other occurrences in the same way. Once through the table, the Pointed-to-Object would be removed. --- Upon having just invented this, there may of course be all kinds of gotchas. (And i hope the above was not too obscure...) Anyhow, this should make code containing no weak references run just as it now does, and code containing weak references slower in proportion to O(n^2) during garbabe collection, where n is the number of weak references -- in the _very_ naive implementation I just described. I assume this would be trivial to implement. Of course, a hash or some other structure would give better performance. And if this is used in a program that does copious amounts of creating and deleting Weak references (as opposed to creating and deleting objects pointed to by them), some of Walter's magic optimizing could do wonders. When a new Weak reference is created, a pair is added to my table, where the flag is off and the pointer points to the Weak reference. When a Weak reference goes out of scope, the corresponding pair is removed from my table. --- I would suspect creating and deleting Weak pointers would not occur that often during a program run. Mostly I assume that weak pointers would exist in "more permanent scopes", thus minimizing the runtime cost of creating and deleting them. ---------- Having written this is not to be understood as I'd endorse weak references as such. I'd much rather see a Pooling Library for D.
Oct 15 2005
parent reply Sean Kelly <sean f4.ca> writes:
In article <43515923.3030504 nospam.org>, Georg Wrede says...
Having written this is not to be understood as I'd endorse weak 
references as such. I'd much rather see a Pooling Library for D.

A pooling library? Sean
Oct 15 2005
parent Georg Wrede <georg.wrede nospam.org> writes:
Sean Kelly wrote:
 In article <43515923.3030504 nospam.org>, Georg Wrede says...
 
Having written this is not to be understood as I'd endorse weak 
references as such. I'd much rather see a Pooling Library for D.

A pooling library?

A web server, a message broker, anything that needs to both create and delete instances all the time, needs something better than weak references. A pooling library would fake the deletions, and therefore it could reuse "deleted" instances whenever new are needed. This really should be in Phobos. It would be natural since we already have GC in D.
Oct 16 2005
prev sibling parent Oskar Linde <olREM OVEnada.kth.se> writes:
Larry Evans wrote:

 On 10/15/2005 11:30 AM, Sean Kelly wrote:
 I'm coming to like the idea of weak pointers in D and have been wondering
 how
 they could be implemented.  The typical smart-pointer approach won't work
 without copy semantics for UDTs, which seems to leave either a syntax
 change (^ as a weak pointer signifier, for example) or perhaps some way
 to flag something
 as a weak pointer to the GC.  The only problem with the GC approach is
 that it
 makes passing  weak pointers to functions somewhat awkward.  I dun't
 suppose someone else can suggest an alternate method?

I'm a D newbie but an experienced C++ programmer; so, pardon me if I'm missing something obvious in my following remarks: Why can't a D use policy_ptr's like the boost::shared_ptr and boost::weak_ptr?

As Sean said, D does unfortunately not suppot custom copy and assignment semantics for UDTs. (Although I see no reason why this should not be made possible for structs...) This means that is is impossible to implement a useful smart_ptr in D.
 A policy based garbage collector: 
 
     policy_gc<SomePolicy>
 
 would know which type by using a template member function
 (does D have these?):

(yes)
     template<typename SomePolicyPtr>
     policy_gc<SomeGcPolicy>::visit_field(SomePolicyPtr& a_ptr)
 
 IOW, SomePolicyPtr could be:
 
    StrongPtr<SomeReferent>
 or:
    WeakPtr<SomeReferent>
 
 and policy_gc<SomeGcPolicy::visit_field would behave appropriately.

Apart from what I said above, this would work. /Oskar
Oct 15 2005