On Friday, August 2, 2019 5:13:10 PM MDT realhet via Digitalmars-d-learn wrote: > Hi, > > I tried to make some resource statistict for my OpenGL Buffer > objects: > > > //here are the things that hold the statistics. > private __gshared{ size_t[int] textureSizeMap, bufferSizeMap; } > > struct GLCounters{ > int programs, shaders, textures, buffers; > size_t textureSize, bufferSize; > } > __gshared GLCounters glCounters; > > ... > > //And this is the buffer creation. > int genBuffer(size_t size){ > int res; glGenBuffers (1, &res); glChk; > glCounters.buffers ++; > glCounters.bufferSize += size; > bufferSizeMap [res] = size; > writefln("buffer allocated %d %d", res, size); > return res; > } > > //Finally, this is the deallocation. If it is called from the GC > (when it destroys a class), it has a big chance to throw an > Invalid Memory Operation exception. > > void deleteBuffer (int handle){ > if(!handle) return; > glDeleteBuffers (1, &handle); glChk; > glCounters.buffers --; > glCounters.bufferSize -= bufferSizeMap [handle]; > writefln("buffer deallocated %d %d", handle, bufferSizeMap > [handle]); > bufferSizeMap.remove(handle); <- this is the problematic part. > } > > -------------------------------------------- > Today I read the documentation about structs, unions and classes, > but I haven't find any restrictions for the ~this() destructors. > > Is there some extra rules regarding the GC and what I must not do > in the destructors? > > I think the destructor always called in the same thread where the > instance was created. This can't be the case. > But what I can guess is: The GC makes a collection and calls my > destructor and inside I do something and the GC calls a > collection again recursively. But it seems a bit crazy, so I > think it's not the case :D > > Please help me solve this! > > *I'm using LDC 1.6.0 Win64
As I understand it, you can't do much of anything that involves the GC inside a destructor that's being run as a finalizer by the GC (as is almost always the case with classes). Structs or classes on the stack (which for classes requires something like scope) don't have that problem, because they're not being run by the GC. But if a struct or class is on the GC heap, then attempting to allocate or deallocate GC resources doesn't work, because the destructor/finalizer runs when the GC is doing a collection. Even trying to use other objects that are on the GC heap from a finalizer is not a allowed, because there is no guarantee about the order that the objects are collected (otherwise, cyclical references would be a big problem), meaning that references in the finalizer could refer to objects that have already been destroyed and their memory freed. https://dlang.org/spec/class.html#destructors Basically, destructors/finalizers for anything on the GC heap are just for cleaning up non-GC-allocated resources. - Jonathan M Davis