Keeping a list of instances and garbage-collection

grauzone none at example.net
Mon Mar 30 23:24:06 PDT 2009


Bill Baxter wrote:
> On Tue, Mar 31, 2009 at 7:37 AM, Christopher Wright <dhasenan at gmail.com> wrote:
>> grauzone wrote:
>>> Christopher Wright wrote:
>>>> grauzone wrote:
>>>>> Jarrett Billingsley wrote:
>>>>>> On Sun, Mar 29, 2009 at 4:42 PM, Leandro Lucarella <llucax at 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



More information about the Digitalmars-d mailing list