Greedy memory handling

H. S. Teoh hsteoh at quickfur.ath.cx
Thu Sep 12 13:11:23 PDT 2013


On Thu, Sep 12, 2013 at 11:13:30PM +0400, Dmitry Olshansky wrote:
> 12-Sep-2013 20:51, H. S. Teoh пишет:
> >On Thu, Sep 12, 2013 at 07:50:25PM +0400, Dmitry Olshansky wrote:
[...]
> >>Better option is to have finalizer hooked up to set some flag. Then
> >>_after_ restoring the pointer we consult that flag variable.
> >
> >Good idea. The problem is, how to set a finalizer on a memory block
> >that can change in size? The OP's original situation was that the
> >buffer can be extended while in use, but I don't know of any D type
> >that can associate a dtor with a ubyte[] array (note that the GC
> >collecting the wrapper struct/class around the ubyte[] is not the
> >same as collecting the actual memory block storing the ubyte[] -- the
> >former can happen without the latter).
> >
> 
> Double indirection? Allocate a class that has finalizer, hold that
> via weak-ref. The wrapper in turn contains a pointer to the buffer.
> The interesting point then is that one may allocate said buffer via
> C's realloc.
> 
> Then once helper struct is collected the finalizer is called and
> this is where we call free to cleanup C's heap.
> 
> I'm thinking this actually is going to work.
[...]

Interesting idea, use C's malloc/realloc to hold the actual buffer. Only
possible catch is, will that cause the GC to collect when it runs out of
memory (which is the whole point of the OP's question)? I.e., does it
make a difference in GC behaviour to allocate, say, 10MB from the GC vs.
allocating 10MB from malloc/realloc?

Assuming we have that settled, something like this should work:

	bool isValid;
	final class BufWrapper {
		void* ptrToMallocedBuf;
		this(void* ptr) {
			// We need this, 'cos otherwise we don't know if
			// our weak ref to BufWrapper is still valid!
			isValid = true;

			ptrToMallocedBuf = ptr;
		}
		~this() {
			// If we're being collected, free the real
			// buffer too.
			free(ptrToMallocedBuf);
			isValid = false;
		}
	}

	// WeakPointer masks the pointer to BufWrapper in some suitable
	// way so that the GC will collect it when needed.
	WeakPointer!BufWrapper wrappedBufRef;

	void doWork(...) {
		void* buf;
		if (!isValid) {
			buf = realloc(null, bufSize);
			wrappedBufRef.set(buf);
		} else {
			buf = wrappedBufRef.get();
		}

		// use buf here.
	}


T

-- 
Public parking: euphemism for paid parking. -- Flora


More information about the Digitalmars-d-learn mailing list