12-Sep-2013 20:51, H. S. Teoh пишет:
On Thu, Sep 12, 2013 at 07:50:25PM +0400, Dmitry Olshansky wrote:
12-Sep-2013 17:51, H. S. Teoh пишет:
[...]
        struct WeakPointer(T) {
                enum size_t mask = 0xdeadbeef;
                union Impl {
                        T* ptr;
                        size_t uintVal;
                }
                Impl impl;
                void set(T* ptr) @system {
                        impl.ptr = ptr;
                        impl.uintVal ^= mask;
                }
                T* get() @system {
                        Impl i = impl;
                        i.uintVal ^= mask;
                        return i.ptr;
                }
        }

        WeakPointer!Buffer bufferRef;

        void doWork(Args...) {
                T* buffer;
                if (bufferRef.get() is null) {
                        // Buffer hasn't been allocated yet
                        buffer = allocateNewBuffer();
                        bufferRef.set(buffer);
                } else {
                        void *p;
                        core.memory.GC.getAttr(p);

This line above is not 100% good idea .. at least with deadbeaf as
mask.

If we do know what OS you compile for we may just flip the say upper
bit and get a pointer into kernel space (and surely that isn't in GC
pool). Even then your last paragraph pretty much destroys it.

Well, that was just an example value. :) If we know which OS it is and
how it assigns VM addresses, then we can adjust the mask appropriately.

But yeah, calling GC.getAttr is unreliable since you can't tell whether
the block is what you had before, or somebody else's new data.


It occured to me that there are modes where full address space is available, typically so on x86 app running on top of x64 kernel (e.g. in Windows Wow64 could do that, Linux also has so-called x32 ABI).


[...]
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.

--
Dmitry Olshansky

Reply via email to