Greedy memory handling
Dmitry Olshansky
dmitry.olsh at gmail.com
Thu Sep 12 12:13:30 PDT 2013
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
More information about the Digitalmars-d-learn
mailing list