Is there a weak pointer or references in D?
Charles Hixson
charleshixsn at earthlink.net
Sat Jan 12 16:49:30 PST 2013
On 01/12/2013 02:04 AM, Era Scarecrow wrote:
> On Saturday, 12 January 2013 at 04:41:00 UTC, Charles Hixson wrote:
>> Thanks. That looks quite useful. OTOH, I don't see how the pointer
>> allows an item to be freed. You probably meant that this was a
>> framework to start development from.
>
> Correct. To create an object if it wasn't there when trying to access it
> basically. That's what I originally thought you wanted; nothing about
> freeing it.
>
>> And it does show a way to auto initialize a null pointer (but that's
>> not where I'm hung up...rather on how to automatically null the
>> pointer when the last valid reference is discarded. It looks as if
>> reference counting is the only feasible way, which isn't what I want.
>> I'd need something that the garbage collector cooperated with. If it
>> hasn't been built already, then a customized approach is
>> better...which doesn't involve weak pointers.)
>>
>> But others points are well taken. A weak reference wouldn't be enough
>> by itself, I'd also need to have the garbage collector prefer to
>> collect stale objects. So what I'll probably do is accompany each item
>> in the structure (Not a struct, but also not just a class. More a
>> collection of structs and classes that work together.) with a sequence
>> counter that's episodically advanced. Then at some point I decide that
>> anything that hasn't been touched since some particular sequence is to
>> be freed. And *THEN* I go back through the entire RAM resident
>> structure and either free the items or subtract the current sequence
>> counter value from them, and then reset the sequence counter to the
>> largest remaining value + 1. When freeing, check if the state needs to
>> be saved.
>
> Hmmmm... I'd just stay with reference counting. If you leave scope with
> a struct it's destructor is handled (and refcounting), if it's a class,
> then it remains 'stale' until the GC collects it, then refcounting is
> updated as everything else is destroyed.
I don't think reference counting would work for my purposes, which is
why I wanted a "weak pointer". There will usually be many live
references at the time I need to release an item. If I'd had weak
pointers I could have made almost all of them weak pointers. I want to
release things that are stale, not things that are unreferenced. I was
trying to avoid needing to cycle through the entire data structure.
>
>> That's the rough idea. Weak pointers will make it easier, but no big
>> deal either way. I may follow your guidance on implementing them, but
>> what I was really hoping for was weak references. Used sort of like:
>>
>> Item item = weak(new Item(params));
>
> Best if you don't... A sorta nice idea, but we don't need to be
> duplicating more of C++'s (boost's?) mistakes.
Well, it doesn't exist, so no problem. But what about that is a
mistake? I haven't used enough C++ to know. (My recent background is
Python, Java, and Ruby...C is way in the background, and the last time I
used C++ heavily was before the STL.)
>
>> With Item being a class. Clearly what weak() returned would need to be
>> an instance of a descendant class of Item. Then I could simply
>> maintain a LRU cache of Items, and clear out the old ones, but not
>> free them before the garbage collector decided it was time. The
>> approach I'm now planning on using frees things in a way that is much
>> less sensitive (I suspect) to current memory pressures. OTOH, I'd need
>> to ensure that Items saved their state (if necessary) before being
>> freed anyway. Handling it "externally" allows this to be ensured by
>> something more definite in timing than a destructor.
>>
>> Still, your design for a weak pointer makes it quite easy for an
>> instance to be created if missing. That may be enough advantage that
>> it would be the best way to proceed.
>>
>> Also, I'm really not enamored of template functions, though I am
>> certainly aware of their power. So the design you offered is one that
>> I would prefer over a templated one. (Besides, each class/struct that
>> I want to have a weak pointer to would have a different way of
>> constructing missing versions. So the template would need so much
>> customization, that it wouldn't be much benefit.)
>
> The template one, (should it have worked) would have had a signature of:
> T* weakPtr(T, V...)(ref T* ptr, V args); //V being default arguments (if
> any)
>
> How it would need to be more customizable I don't know; Alternatively a
> delegate could have been included making only a lamba needed in key
> locations.
Some of the items have heavy data inclusions, and they would get passed
around as pointers, some of them are light, and they'd be structs. Some
could be automatically calculated from the creation parameters, others
need to be read in from files. And these cause different values
returned from functions doing abstractly the same job.
>
>> The only things I dislike about you design are things I dislike about
>> all designs that use pointers...and I *did* ask for such a design.
>
> Yes you did. But since you can't use 'ref' as part of a variable's
> signature (outside of function declarations) you'd have to to use
> pointers instead. Just try to be as safe as possible. With pointer
> arithmetic being unsafe and mostly unused (unneeded due to the arrays)
> it's just a matter of allocating and accessing the pointer that's safe
> (or as much as using classes anyways).
If I'd been able to have actual weak pointers, that would be worthwhile.
As it is...I'm going to use references (i.e., class instances) as the
external interfaces. Internally, things will often be quite a bit
different. (Yeah, maybe I should say handle rather than reference. I'm
not sure. I *am* sure I like the syntax of class instances a lot better
than I do pointers to structs.)
More information about the Digitalmars-d-learn
mailing list