I have a C++ map which manages loaded regions. Each region has an associated MTLBuffer for the geometry generated after the region data is converted into a mesh. The idea is to store a reference to each buffer inside the C++ map so I have all of the regions and their associated data in a single data structure. I could have this Objective-C++ pseudocode:

struct Region {
    void *buffer;
    // Other fields
};
std::unordered_map<uint64_t, Region> loaded_regions;
void render_region(Region *region) {
    float vertices[MAX_SIZE];
    unsigned length;

    // ...

    // There are multiple ways I could do this. One could be:
    map[position].buffer = [device newBufferWithBytes: vertices length: length options: MTLStorageModeShared];

    // I could also pass `vertices` to some external function defined in Swift that creates a new `MTLBuffer` and returns it.
    // This is then converted to a bare pointer and stored in the map.
}

However, when regions are deleted from the map, for example in a function like this:

void delete_region(uint16_t position) {
    Region *region = loaded_regions[position];

    // ...

    map.erase(position);
    delete position;
}

How can I ensure any stored Swift object references or Objective-C object references are properly released and no memory leak is caused, assuming I have ARC enabled?

Is this possible, or will I just have to make a Swift Dictionary or an Objective-C NSDictionary to store these buffers independently from the C++ map that stores the actual regions?

When ARC is enabled, Xcode will not allow release messages to be used directly, so I do not know how else to manually free the memory.

1

There are 1 best solutions below

2
273K On BEST ANSWER

It's quite easy with smart pointers. See the sketch below.

struct Deleter {
    void operator()(void *buffer) const nothrow { CFRelease(buffer); }
};

struct Region {
    std::unique_ptr<void, Deleter> buffer;
    // Other fields
};

map[positon].buffer.reset([device newBufferWithBytes:vertices
                                              length:length
                                             options:MTLStorageModeShared]);