Bill Baxter wrote:
On Tue, Mar 31, 2009 at 7:37 AM, Christopher Wright <dhase...@gmail.com> wrote:
grauzone wrote:
Christopher Wright wrote:
grauzone wrote:
Jarrett Billingsley wrote:
On Sun, Mar 29, 2009 at 4:42 PM, Leandro Lucarella <llu...@gmail.com>
wrote:
This was discussed several times in the past. For example:
http://www.digitalmars.com/d/archives/digitalmars/D/learn/weak_references_13301.html
http://www.digitalmars.com/d/archives/digitalmars/D/learn/Soft_weak_references_8264.html
http://www.digitalmars.com/d/archives/digitalmars/D/announce/ANN_WeakObjectReference_-_class_to_hold_weak_references_9103.html
etc.
I hope it helps.
The one provided by Bill:
http://www.dsource.org/projects/scrapple/browser/trunk/weakref
seems to work fine, and has the advantage of working in both Phobos and
Tango.
First, I doubt this actually works. The WeakRef stores the pointer as
size_t, but the GC is conservative and will still recognize the size_t as a
pointer. The unittest in the existing code only works, because he uses an
explicit delete on the referenced object.
If the WeakRef is on the stack, this is true.
If the WeakRef is part of an aggregate type that contains pointers, this
is true.
If WeakRef is a class, this is also true. Because all objects contain a
hidden monitor pointer, and the monitor is subject to garbage collection
AFAIK.
Otherwise, the GC will see that the relevant block is marked as having no
pointers.
True -- weakref is a difficult thing to make thread-safe.
It seems there's still work to do, and a thread-safe WeakRef can't be
created with the current interfaces. Is this true?
I'm thinking rt_attachDisposeEvent() should take a *pointer* to the
reference instead of the reference itself (effectively a double pointer),
and clear this pointer during garbage collection, when all threads are still
globally locked.
Hold on, I think this isn't a real issue.
You have essentially:
class WeakRef
{
const xor = 0x101010101;
size_t value;
bool collected;
Object toObject()
{
if (collected) return null;
auto ptr = cast(void*)(value ^ xor);
auto obj = *cast(Object*)&ptr;
if (collected) return null;
return obj;
}
}
After casting, you have a strong reference to the object, so it's impossible
for the object to be collected if it hasn't yet been collected. If the
object was collected between the two checks, you just have an invalid object
reference that nobody ever uses. As long as the compiler doesn't do nasty
reordering things, you should be fine.
Ooops, that looks OK. This makes me happy; at least I can use weak
pointers in my own program now (and remove that nasty hack that emulated
them).
Pardon my ignorance, but how do you know that ptr ^ xor is not a
pointer to some other real object in memory? Does the language give
you some guarantee that it won't ever be a valid pointer?
Not really, but it could be "good enough". Here's another way to trick
the GC in a more reliable way:
union hide_ptr {
void* ptr;
byte[4] stuff;
}
class WeakRef {
byte[5] hidden_pointer;
this(void* ptr) {
hide_ptr p;
p.ptr = ptr;
hidden_pointer[1..5] = p.stuff;
}
}
This should work because the GC expects all pointers to be on 4 byte
aligned boundaries (or 8 bytes in 64 bit mode).
--bb